Home | History | Annotate | Download | only in ControlPanel
      1 /* -*- Mode: C; tab-width: 4 -*-
      2  *
      3  * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 
     18 #include "SecondPage.h"
     19 #include "resource.h"
     20 
     21 #include "ConfigPropertySheet.h"
     22 #include "SharedSecret.h"
     23 
     24 #include <WinServices.h>
     25 
     26 #define MAX_KEY_LENGTH 255
     27 
     28 IMPLEMENT_DYNCREATE(CSecondPage, CPropertyPage)
     29 
     30 
     31 //---------------------------------------------------------------------------------------------------------------------------
     32 //	CSecondPage::CSecondPage
     33 //---------------------------------------------------------------------------------------------------------------------------
     34 
     35 CSecondPage::CSecondPage()
     36 :
     37 	CPropertyPage(CSecondPage::IDD),
     38 	m_setupKey( NULL )
     39 {
     40 	//{{AFX_DATA_INIT(CSecondPage)
     41 	//}}AFX_DATA_INIT
     42 
     43 	OSStatus err;
     44 
     45 	err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\DynDNS\\Setup\\" kServiceDynDNSRegistrationDomains, 0,
     46 	                      NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE|KEY_WOW64_32KEY, NULL, &m_setupKey, NULL );
     47 	check_noerr( err );
     48 }
     49 
     50 
     51 //---------------------------------------------------------------------------------------------------------------------------
     52 //	CSecondPage::~CSecondPage
     53 //---------------------------------------------------------------------------------------------------------------------------
     54 
     55 CSecondPage::~CSecondPage()
     56 {
     57 	if ( m_setupKey )
     58 	{
     59 		RegCloseKey( m_setupKey );
     60 		m_setupKey = NULL;
     61 	}
     62 }
     63 
     64 
     65 //---------------------------------------------------------------------------------------------------------------------------
     66 //	CSecondPage::DoDataExchange
     67 //---------------------------------------------------------------------------------------------------------------------------
     68 
     69 void CSecondPage::DoDataExchange(CDataExchange* pDX)
     70 {
     71 	CPropertyPage::DoDataExchange(pDX);
     72 	//{{AFX_DATA_MAP(CSecondPage)
     73 	//}}AFX_DATA_MAP
     74 	DDX_Control(pDX, IDC_CHECK1, m_advertiseServicesButton);
     75 	DDX_Control(pDX, IDC_BUTTON1, m_sharedSecretButton);
     76 	DDX_Control(pDX, IDC_COMBO2, m_regDomainsBox);
     77 }
     78 
     79 BEGIN_MESSAGE_MAP(CSecondPage, CPropertyPage)
     80 	//{{AFX_MSG_MAP(CSecondPage)
     81 	//}}AFX_MSG_MAP
     82 	ON_BN_CLICKED(IDC_BUTTON1, OnBnClickedSharedSecret)
     83 	ON_BN_CLICKED(IDC_CHECK1, OnBnClickedAdvertise)
     84 	ON_CBN_SELCHANGE(IDC_COMBO1, OnCbnSelChange)
     85 	ON_CBN_EDITCHANGE(IDC_COMBO1, OnCbnEditChange)
     86 	ON_CBN_EDITCHANGE(IDC_COMBO2, OnCbnEditChange)
     87 	ON_CBN_SELCHANGE(IDC_COMBO2, OnCbnSelChange)
     88 
     89 END_MESSAGE_MAP()
     90 
     91 
     92 //---------------------------------------------------------------------------------------------------------------------------
     93 //	CSecondPage::SetModified
     94 //---------------------------------------------------------------------------------------------------------------------------
     95 
     96 void CSecondPage::SetModified( BOOL bChanged )
     97 {
     98 	m_modified = bChanged;
     99 
    100 	CPropertyPage::SetModified( bChanged );
    101 }
    102 
    103 
    104 //---------------------------------------------------------------------------------------------------------------------------
    105 //	CSecondPage::OnSetActive
    106 //---------------------------------------------------------------------------------------------------------------------------
    107 
    108 BOOL
    109 CSecondPage::OnSetActive()
    110 {
    111 	CConfigPropertySheet	*	psheet;
    112 	DWORD						err;
    113 	BOOL						b = CPropertyPage::OnSetActive();
    114 
    115 	psheet = reinterpret_cast<CConfigPropertySheet*>(GetParent());
    116 	require_quiet( psheet, exit );
    117 
    118 	m_modified = FALSE;
    119 
    120 	// Clear out what's there
    121 
    122 	EmptyComboBox( m_regDomainsBox );
    123 
    124 	// Now populate the registration domain box
    125 
    126 	err = Populate( m_regDomainsBox, m_setupKey, psheet->m_regDomains );
    127 	check_noerr( err );
    128 
    129 exit:
    130 
    131 	return b;
    132 }
    133 
    134 
    135 //---------------------------------------------------------------------------------------------------------------------------
    136 //	CSecondPage::OnOK
    137 //---------------------------------------------------------------------------------------------------------------------------
    138 
    139 void
    140 CSecondPage::OnOK()
    141 {
    142 	if ( m_modified )
    143 	{
    144 		Commit();
    145 	}
    146 }
    147 
    148 
    149 
    150 //---------------------------------------------------------------------------------------------------------------------------
    151 //	CSecondPage::Commit
    152 //---------------------------------------------------------------------------------------------------------------------------
    153 
    154 void
    155 CSecondPage::Commit()
    156 {
    157 	DWORD err;
    158 
    159 	if ( m_setupKey != NULL )
    160 	{
    161 		err = Commit( m_regDomainsBox, m_setupKey, m_advertiseServicesButton.GetCheck() == BST_CHECKED );
    162 		check_noerr( err );
    163 	}
    164 }
    165 
    166 
    167 //---------------------------------------------------------------------------------------------------------------------------
    168 //	CSecondPage::Commit
    169 //---------------------------------------------------------------------------------------------------------------------------
    170 
    171 OSStatus
    172 CSecondPage::Commit( CComboBox & box, HKEY key, DWORD enabled )
    173 {
    174 	CString		selected;
    175 	HKEY		subKey	= NULL;
    176 	TCHAR		subKeyName[MAX_KEY_LENGTH];
    177 	DWORD		cSubKeys = 0;
    178 	DWORD		cbMaxSubKey;
    179 	DWORD		cchMaxClass;
    180 	DWORD		dwSize;
    181 	int			i;
    182 	OSStatus	err = kNoErr;
    183 
    184 	// First, remove all the entries that are there
    185 
    186     err = RegQueryInfoKey( key, NULL, NULL, NULL, &cSubKeys, &cbMaxSubKey, &cchMaxClass, NULL, NULL, NULL, NULL, NULL );
    187 	require_noerr( err, exit );
    188 
    189 	for ( i = 0; i < (int) cSubKeys; i++ )
    190 	{
    191 		dwSize = MAX_KEY_LENGTH;
    192 
    193 		err = RegEnumKeyEx( key, 0, subKeyName, &dwSize, NULL, NULL, NULL, NULL );
    194 		require_noerr( err, exit );
    195 
    196 		err = RegDeleteKey( key, subKeyName );
    197 		require_noerr( err, exit );
    198 	}
    199 
    200 	// Get selected text
    201 
    202 	box.GetWindowText( selected );
    203 
    204 	// If we haven't seen this string before, add the string to the box and
    205 	// the registry
    206 
    207 	if ( ( selected.GetLength() > 0 ) && ( box.FindStringExact( -1, selected ) == CB_ERR ) )
    208 	{
    209 		CString string;
    210 
    211 		box.AddString( selected );
    212 
    213 		err = RegQueryString( key, L"UserDefined", string );
    214 		check_noerr( err );
    215 
    216 		if ( string.GetLength() )
    217 		{
    218 			string += L"," + selected;
    219 		}
    220 		else
    221 		{
    222 			string = selected;
    223 		}
    224 
    225 		err = RegSetValueEx( key, L"UserDefined", 0, REG_SZ, (LPBYTE) (LPCTSTR) string, ( string.GetLength() + 1) * sizeof( TCHAR ) );
    226 		check_noerr ( err );
    227 	}
    228 
    229 	// Save selected text in registry.  This will trigger mDNSResponder to setup
    230 	// DynDNS config again
    231 
    232 	err = RegCreateKeyEx( key, selected, 0,
    233 	                      NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE|KEY_WOW64_32KEY, NULL, &subKey, NULL );
    234 	require_noerr( err, exit );
    235 
    236 	err = RegSetValueEx( subKey, L"Enabled", 0, REG_DWORD, (LPBYTE) &enabled, sizeof( DWORD ) );
    237 	check_noerr( err );
    238 
    239 exit:
    240 
    241 	if ( subKey )
    242 	{
    243 		RegCloseKey( subKey );
    244 		subKey = NULL;
    245 	}
    246 
    247 	return err;
    248 }
    249 
    250 
    251 //---------------------------------------------------------------------------------------------------------------------------
    252 //	CSecondPage::OnBnClickedSharedSecret
    253 //---------------------------------------------------------------------------------------------------------------------------
    254 
    255 void CSecondPage::OnBnClickedSharedSecret()
    256 {
    257 	CString name;
    258 
    259 	m_regDomainsBox.GetWindowText( name );
    260 
    261 	CSharedSecret dlg;
    262 
    263 	dlg.Load( name );
    264 
    265 	if ( dlg.DoModal() == IDOK )
    266 	{
    267 		DWORD		wakeup = 0;
    268 		DWORD		dwSize = sizeof( DWORD );
    269 		OSStatus	err;
    270 
    271 		dlg.Commit( name );
    272 
    273 		// We have now updated the secret, however the system service
    274 		// doesn't know about it yet.  So we're going to update the
    275 		// registry with a dummy value which will cause the system
    276 		// service to re-initialize it's DynDNS setup
    277 		//
    278 
    279 		RegQueryValueEx( m_setupKey, L"Wakeup", NULL, NULL, (LPBYTE) &wakeup, &dwSize );
    280 
    281 		wakeup++;
    282 
    283 		err = RegSetValueEx( m_setupKey, L"Wakeup", 0, REG_DWORD, (LPBYTE) &wakeup, sizeof( DWORD ) );
    284 		require_noerr( err, exit );
    285 	}
    286 
    287 exit:
    288 
    289 	return;
    290 }
    291 
    292 
    293 //---------------------------------------------------------------------------------------------------------------------------
    294 //	CSecondPage::OnBnClickedAdvertise
    295 //---------------------------------------------------------------------------------------------------------------------------
    296 
    297 void CSecondPage::OnBnClickedAdvertise()
    298 {
    299 	int state;
    300 
    301 	state = m_advertiseServicesButton.GetCheck();
    302 
    303 	m_regDomainsBox.EnableWindow( state );
    304 	m_sharedSecretButton.EnableWindow( state );
    305 
    306 	SetModified( TRUE );
    307 }
    308 
    309 
    310 //---------------------------------------------------------------------------------------------------------------------------
    311 //	CSecondPage::OnCbnSelChange
    312 //---------------------------------------------------------------------------------------------------------------------------
    313 
    314 void CSecondPage::OnCbnSelChange()
    315 {
    316 	SetModified( TRUE );
    317 }
    318 
    319 
    320 //---------------------------------------------------------------------------------------------------------------------------
    321 //	CSecondPage::OnCbnEditChange
    322 //---------------------------------------------------------------------------------------------------------------------------
    323 
    324 void CSecondPage::OnCbnEditChange()
    325 {
    326 	SetModified( TRUE );
    327 }
    328 
    329 
    330 
    331 //---------------------------------------------------------------------------------------------------------------------------
    332 //	CSecondPage::OnAddRegistrationDomain
    333 //---------------------------------------------------------------------------------------------------------------------------
    334 
    335 void
    336 CSecondPage::OnAddRegistrationDomain( CString & domain )
    337 {
    338 	int index = m_regDomainsBox.FindStringExact( -1, domain );
    339 
    340 	if ( index == CB_ERR )
    341 	{
    342 		m_regDomainsBox.AddString( domain );
    343 	}
    344 }
    345 
    346 
    347 //---------------------------------------------------------------------------------------------------------------------------
    348 //	CSecondPage::OnRemoveRegistrationDomain
    349 //---------------------------------------------------------------------------------------------------------------------------
    350 
    351 void
    352 CSecondPage::OnRemoveRegistrationDomain( CString & domain )
    353 {
    354 	int index = m_regDomainsBox.FindStringExact( -1, domain );
    355 
    356 	if ( index != CB_ERR )
    357 	{
    358 		m_regDomainsBox.DeleteString( index );
    359 	}
    360 }
    361 
    362 
    363 //---------------------------------------------------------------------------------------------------------------------------
    364 //	CSecondPage::EmptyComboBox
    365 //---------------------------------------------------------------------------------------------------------------------------
    366 
    367 void
    368 CSecondPage::EmptyComboBox( CComboBox & box )
    369 {
    370 	while ( box.GetCount() > 0 )
    371 	{
    372 		box.DeleteString( 0 );
    373 	}
    374 }
    375 
    376 
    377 //---------------------------------------------------------------------------------------------------------------------------
    378 //	CSecondPage::Populate
    379 //---------------------------------------------------------------------------------------------------------------------------
    380 
    381 OSStatus
    382 CSecondPage::Populate( CComboBox & box, HKEY key, StringList & l )
    383 {
    384 	CString		string;
    385 	HKEY		subKey = NULL;
    386 	DWORD		dwSize;
    387 	DWORD		enabled = 0;
    388 	TCHAR		subKeyName[MAX_KEY_LENGTH];
    389 	DWORD		cSubKeys = 0;
    390 	DWORD		cbMaxSubKey;
    391 	DWORD		cchMaxClass;
    392 	OSStatus	err;
    393 
    394 	err = RegQueryString( key, L"UserDefined", string );
    395 
    396 	if ( !err && string.GetLength() )
    397 	{
    398 		bool done = false;
    399 
    400 		while ( !done )
    401 		{
    402 			CString tok;
    403 
    404 			tok = string.SpanExcluding( L"," );
    405 
    406 			box.AddString( tok );
    407 
    408 			if ( tok != string )
    409 			{
    410 				// Get rid of that string and comma
    411 
    412 				string = string.Right( string.GetLength() - tok.GetLength() - 1 );
    413 			}
    414 			else
    415 			{
    416 				done = true;
    417 			}
    418 		}
    419 	}
    420 
    421 	StringList::iterator it;
    422 
    423 	for ( it = l.begin(); it != l.end(); it++ )
    424 	{
    425 		if ( box.FindStringExact( -1, *it ) == CB_ERR )
    426 		{
    427 			box.AddString( *it );
    428 		}
    429 	}
    430 
    431 	err = RegQueryInfoKey( key, NULL, NULL, NULL, &cSubKeys, &cbMaxSubKey, &cchMaxClass, NULL, NULL, NULL, NULL, NULL );
    432 	require_noerr( err, exit );
    433 
    434 	if ( cSubKeys > 0 )
    435 	{
    436 		dwSize = MAX_KEY_LENGTH;
    437 
    438 		err = RegEnumKeyEx( key, 0, subKeyName, &dwSize, NULL, NULL, NULL, NULL );
    439 		require_noerr( err, exit );
    440 
    441 		err = RegOpenKey( key, subKeyName, &subKey );
    442 		require_noerr( err, exit );
    443 
    444 		dwSize = sizeof( DWORD );
    445 		err = RegQueryValueEx( subKey, L"Enabled", NULL, NULL, (LPBYTE) &enabled, &dwSize );
    446 		require_noerr( err, exit );
    447 
    448 		// See if it's there
    449 
    450 		if ( box.SelectString( -1, subKeyName ) == CB_ERR )
    451 		{
    452 			// If not, add it
    453 
    454 			box.AddString( subKeyName );
    455 		}
    456 
    457 		box.SelectString( -1, subKeyName );
    458 
    459 		RegCloseKey( subKey );
    460 		subKey = NULL;
    461 	}
    462 
    463 exit:
    464 
    465 	m_advertiseServicesButton.SetCheck( ( !err && enabled ) ? BST_CHECKED : BST_UNCHECKED );
    466 	m_regDomainsBox.EnableWindow( ( !err && enabled ) );
    467 	m_sharedSecretButton.EnableWindow( (!err && enabled ) );
    468 
    469 	return err;
    470 }
    471 
    472 
    473 //---------------------------------------------------------------------------------------------------------------------------
    474 //	CSecondPage::CreateKey
    475 //---------------------------------------------------------------------------------------------------------------------------
    476 
    477 OSStatus
    478 CSecondPage::CreateKey( CString & name, DWORD enabled )
    479 {
    480 	HKEY		key = NULL;
    481 	OSStatus	err;
    482 
    483 	err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, (LPCTSTR) name, 0,
    484 		                  NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE|KEY_WOW64_32KEY, NULL, &key, NULL );
    485 	require_noerr( err, exit );
    486 
    487 	err = RegSetValueEx( key, L"Enabled", 0, REG_DWORD, (LPBYTE) &enabled, sizeof( DWORD ) );
    488 	check_noerr( err );
    489 
    490 exit:
    491 
    492 	if ( key )
    493 	{
    494 		RegCloseKey( key );
    495 	}
    496 
    497 	return err;
    498 }
    499 
    500 
    501 //---------------------------------------------------------------------------------------------------------------------------
    502 //	CSecondPage::RegQueryString
    503 //---------------------------------------------------------------------------------------------------------------------------
    504 
    505 OSStatus
    506 CSecondPage::RegQueryString( HKEY key, CString valueName, CString & value )
    507 {
    508 	TCHAR	*	string;
    509 	DWORD		stringLen;
    510 	int			i;
    511 	OSStatus	err;
    512 
    513 	stringLen	= 1024;
    514 	string		= NULL;
    515 	i			= 0;
    516 
    517 	do
    518 	{
    519 		if ( string )
    520 		{
    521 			free( string );
    522 		}
    523 
    524 		string = (TCHAR*) malloc( stringLen );
    525 		require_action( string, exit, err = kUnknownErr );
    526 		*string = '\0';
    527 
    528 		err = RegQueryValueEx( key, valueName, 0, NULL, (LPBYTE) string, &stringLen );
    529 
    530 		i++;
    531 	}
    532 	while ( ( err == ERROR_MORE_DATA ) && ( i < 100 ) );
    533 
    534 	value = string;
    535 
    536 exit:
    537 
    538 	if ( string )
    539 	{
    540 		free( string );
    541 	}
    542 
    543 	return err;
    544 }
    545