/* -*- Mode: C; tab-width: 4 -*- * * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "SecondPage.h" #include "resource.h" #include "ConfigPropertySheet.h" #include "SharedSecret.h" #include <WinServices.h> #define MAX_KEY_LENGTH 255 IMPLEMENT_DYNCREATE(CSecondPage, CPropertyPage) //--------------------------------------------------------------------------------------------------------------------------- // CSecondPage::CSecondPage //--------------------------------------------------------------------------------------------------------------------------- CSecondPage::CSecondPage() : CPropertyPage(CSecondPage::IDD), m_setupKey( NULL ) { //{{AFX_DATA_INIT(CSecondPage) //}}AFX_DATA_INIT OSStatus err; err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\DynDNS\\Setup\\" kServiceDynDNSRegistrationDomains, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE|KEY_WOW64_32KEY, NULL, &m_setupKey, NULL ); check_noerr( err ); } //--------------------------------------------------------------------------------------------------------------------------- // CSecondPage::~CSecondPage //--------------------------------------------------------------------------------------------------------------------------- CSecondPage::~CSecondPage() { if ( m_setupKey ) { RegCloseKey( m_setupKey ); m_setupKey = NULL; } } //--------------------------------------------------------------------------------------------------------------------------- // CSecondPage::DoDataExchange //--------------------------------------------------------------------------------------------------------------------------- void CSecondPage::DoDataExchange(CDataExchange* pDX) { CPropertyPage::DoDataExchange(pDX); //{{AFX_DATA_MAP(CSecondPage) //}}AFX_DATA_MAP DDX_Control(pDX, IDC_CHECK1, m_advertiseServicesButton); DDX_Control(pDX, IDC_BUTTON1, m_sharedSecretButton); DDX_Control(pDX, IDC_COMBO2, m_regDomainsBox); } BEGIN_MESSAGE_MAP(CSecondPage, CPropertyPage) //{{AFX_MSG_MAP(CSecondPage) //}}AFX_MSG_MAP ON_BN_CLICKED(IDC_BUTTON1, OnBnClickedSharedSecret) ON_BN_CLICKED(IDC_CHECK1, OnBnClickedAdvertise) ON_CBN_SELCHANGE(IDC_COMBO1, OnCbnSelChange) ON_CBN_EDITCHANGE(IDC_COMBO1, OnCbnEditChange) ON_CBN_EDITCHANGE(IDC_COMBO2, OnCbnEditChange) ON_CBN_SELCHANGE(IDC_COMBO2, OnCbnSelChange) END_MESSAGE_MAP() //--------------------------------------------------------------------------------------------------------------------------- // CSecondPage::SetModified //--------------------------------------------------------------------------------------------------------------------------- void CSecondPage::SetModified( BOOL bChanged ) { m_modified = bChanged; CPropertyPage::SetModified( bChanged ); } //--------------------------------------------------------------------------------------------------------------------------- // CSecondPage::OnSetActive //--------------------------------------------------------------------------------------------------------------------------- BOOL CSecondPage::OnSetActive() { CConfigPropertySheet * psheet; DWORD err; BOOL b = CPropertyPage::OnSetActive(); psheet = reinterpret_cast<CConfigPropertySheet*>(GetParent()); require_quiet( psheet, exit ); m_modified = FALSE; // Clear out what's there EmptyComboBox( m_regDomainsBox ); // Now populate the registration domain box err = Populate( m_regDomainsBox, m_setupKey, psheet->m_regDomains ); check_noerr( err ); exit: return b; } //--------------------------------------------------------------------------------------------------------------------------- // CSecondPage::OnOK //--------------------------------------------------------------------------------------------------------------------------- void CSecondPage::OnOK() { if ( m_modified ) { Commit(); } } //--------------------------------------------------------------------------------------------------------------------------- // CSecondPage::Commit //--------------------------------------------------------------------------------------------------------------------------- void CSecondPage::Commit() { DWORD err; if ( m_setupKey != NULL ) { err = Commit( m_regDomainsBox, m_setupKey, m_advertiseServicesButton.GetCheck() == BST_CHECKED ); check_noerr( err ); } } //--------------------------------------------------------------------------------------------------------------------------- // CSecondPage::Commit //--------------------------------------------------------------------------------------------------------------------------- OSStatus CSecondPage::Commit( CComboBox & box, HKEY key, DWORD enabled ) { CString selected; HKEY subKey = NULL; TCHAR subKeyName[MAX_KEY_LENGTH]; DWORD cSubKeys = 0; DWORD cbMaxSubKey; DWORD cchMaxClass; DWORD dwSize; int i; OSStatus err = kNoErr; // First, remove all the entries that are there err = RegQueryInfoKey( key, NULL, NULL, NULL, &cSubKeys, &cbMaxSubKey, &cchMaxClass, NULL, NULL, NULL, NULL, NULL ); require_noerr( err, exit ); for ( i = 0; i < (int) cSubKeys; i++ ) { dwSize = MAX_KEY_LENGTH; err = RegEnumKeyEx( key, 0, subKeyName, &dwSize, NULL, NULL, NULL, NULL ); require_noerr( err, exit ); err = RegDeleteKey( key, subKeyName ); require_noerr( err, exit ); } // Get selected text box.GetWindowText( selected ); // If we haven't seen this string before, add the string to the box and // the registry if ( ( selected.GetLength() > 0 ) && ( box.FindStringExact( -1, selected ) == CB_ERR ) ) { CString string; box.AddString( selected ); err = RegQueryString( key, L"UserDefined", string ); check_noerr( err ); if ( string.GetLength() ) { string += L"," + selected; } else { string = selected; } err = RegSetValueEx( key, L"UserDefined", 0, REG_SZ, (LPBYTE) (LPCTSTR) string, ( string.GetLength() + 1) * sizeof( TCHAR ) ); check_noerr ( err ); } // Save selected text in registry. This will trigger mDNSResponder to setup // DynDNS config again err = RegCreateKeyEx( key, selected, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE|KEY_WOW64_32KEY, NULL, &subKey, NULL ); require_noerr( err, exit ); err = RegSetValueEx( subKey, L"Enabled", 0, REG_DWORD, (LPBYTE) &enabled, sizeof( DWORD ) ); check_noerr( err ); exit: if ( subKey ) { RegCloseKey( subKey ); subKey = NULL; } return err; } //--------------------------------------------------------------------------------------------------------------------------- // CSecondPage::OnBnClickedSharedSecret //--------------------------------------------------------------------------------------------------------------------------- void CSecondPage::OnBnClickedSharedSecret() { CString name; m_regDomainsBox.GetWindowText( name ); CSharedSecret dlg; dlg.Load( name ); if ( dlg.DoModal() == IDOK ) { DWORD wakeup = 0; DWORD dwSize = sizeof( DWORD ); OSStatus err; dlg.Commit( name ); // We have now updated the secret, however the system service // doesn't know about it yet. So we're going to update the // registry with a dummy value which will cause the system // service to re-initialize it's DynDNS setup // RegQueryValueEx( m_setupKey, L"Wakeup", NULL, NULL, (LPBYTE) &wakeup, &dwSize ); wakeup++; err = RegSetValueEx( m_setupKey, L"Wakeup", 0, REG_DWORD, (LPBYTE) &wakeup, sizeof( DWORD ) ); require_noerr( err, exit ); } exit: return; } //--------------------------------------------------------------------------------------------------------------------------- // CSecondPage::OnBnClickedAdvertise //--------------------------------------------------------------------------------------------------------------------------- void CSecondPage::OnBnClickedAdvertise() { int state; state = m_advertiseServicesButton.GetCheck(); m_regDomainsBox.EnableWindow( state ); m_sharedSecretButton.EnableWindow( state ); SetModified( TRUE ); } //--------------------------------------------------------------------------------------------------------------------------- // CSecondPage::OnCbnSelChange //--------------------------------------------------------------------------------------------------------------------------- void CSecondPage::OnCbnSelChange() { SetModified( TRUE ); } //--------------------------------------------------------------------------------------------------------------------------- // CSecondPage::OnCbnEditChange //--------------------------------------------------------------------------------------------------------------------------- void CSecondPage::OnCbnEditChange() { SetModified( TRUE ); } //--------------------------------------------------------------------------------------------------------------------------- // CSecondPage::OnAddRegistrationDomain //--------------------------------------------------------------------------------------------------------------------------- void CSecondPage::OnAddRegistrationDomain( CString & domain ) { int index = m_regDomainsBox.FindStringExact( -1, domain ); if ( index == CB_ERR ) { m_regDomainsBox.AddString( domain ); } } //--------------------------------------------------------------------------------------------------------------------------- // CSecondPage::OnRemoveRegistrationDomain //--------------------------------------------------------------------------------------------------------------------------- void CSecondPage::OnRemoveRegistrationDomain( CString & domain ) { int index = m_regDomainsBox.FindStringExact( -1, domain ); if ( index != CB_ERR ) { m_regDomainsBox.DeleteString( index ); } } //--------------------------------------------------------------------------------------------------------------------------- // CSecondPage::EmptyComboBox //--------------------------------------------------------------------------------------------------------------------------- void CSecondPage::EmptyComboBox( CComboBox & box ) { while ( box.GetCount() > 0 ) { box.DeleteString( 0 ); } } //--------------------------------------------------------------------------------------------------------------------------- // CSecondPage::Populate //--------------------------------------------------------------------------------------------------------------------------- OSStatus CSecondPage::Populate( CComboBox & box, HKEY key, StringList & l ) { CString string; HKEY subKey = NULL; DWORD dwSize; DWORD enabled = 0; TCHAR subKeyName[MAX_KEY_LENGTH]; DWORD cSubKeys = 0; DWORD cbMaxSubKey; DWORD cchMaxClass; OSStatus err; err = RegQueryString( key, L"UserDefined", string ); if ( !err && string.GetLength() ) { bool done = false; while ( !done ) { CString tok; tok = string.SpanExcluding( L"," ); box.AddString( tok ); if ( tok != string ) { // Get rid of that string and comma string = string.Right( string.GetLength() - tok.GetLength() - 1 ); } else { done = true; } } } StringList::iterator it; for ( it = l.begin(); it != l.end(); it++ ) { if ( box.FindStringExact( -1, *it ) == CB_ERR ) { box.AddString( *it ); } } err = RegQueryInfoKey( key, NULL, NULL, NULL, &cSubKeys, &cbMaxSubKey, &cchMaxClass, NULL, NULL, NULL, NULL, NULL ); require_noerr( err, exit ); if ( cSubKeys > 0 ) { dwSize = MAX_KEY_LENGTH; err = RegEnumKeyEx( key, 0, subKeyName, &dwSize, NULL, NULL, NULL, NULL ); require_noerr( err, exit ); err = RegOpenKey( key, subKeyName, &subKey ); require_noerr( err, exit ); dwSize = sizeof( DWORD ); err = RegQueryValueEx( subKey, L"Enabled", NULL, NULL, (LPBYTE) &enabled, &dwSize ); require_noerr( err, exit ); // See if it's there if ( box.SelectString( -1, subKeyName ) == CB_ERR ) { // If not, add it box.AddString( subKeyName ); } box.SelectString( -1, subKeyName ); RegCloseKey( subKey ); subKey = NULL; } exit: m_advertiseServicesButton.SetCheck( ( !err && enabled ) ? BST_CHECKED : BST_UNCHECKED ); m_regDomainsBox.EnableWindow( ( !err && enabled ) ); m_sharedSecretButton.EnableWindow( (!err && enabled ) ); return err; } //--------------------------------------------------------------------------------------------------------------------------- // CSecondPage::CreateKey //--------------------------------------------------------------------------------------------------------------------------- OSStatus CSecondPage::CreateKey( CString & name, DWORD enabled ) { HKEY key = NULL; OSStatus err; err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, (LPCTSTR) name, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE|KEY_WOW64_32KEY, NULL, &key, NULL ); require_noerr( err, exit ); err = RegSetValueEx( key, L"Enabled", 0, REG_DWORD, (LPBYTE) &enabled, sizeof( DWORD ) ); check_noerr( err ); exit: if ( key ) { RegCloseKey( key ); } return err; } //--------------------------------------------------------------------------------------------------------------------------- // CSecondPage::RegQueryString //--------------------------------------------------------------------------------------------------------------------------- OSStatus CSecondPage::RegQueryString( HKEY key, CString valueName, CString & value ) { TCHAR * string; DWORD stringLen; int i; OSStatus err; stringLen = 1024; string = NULL; i = 0; do { if ( string ) { free( string ); } string = (TCHAR*) malloc( stringLen ); require_action( string, exit, err = kUnknownErr ); *string = '\0'; err = RegQueryValueEx( key, valueName, 0, NULL, (LPBYTE) string, &stringLen ); i++; } while ( ( err == ERROR_MORE_DATA ) && ( i < 100 ) ); value = string; exit: if ( string ) { free( string ); } return err; }