Revert "Imported Upstream version 1096.40.7"
[platform/upstream/mdnsresponder.git] / mDNSWindows / ControlPanel / SecondPage.cpp
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, 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, 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, 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 }