1 /* -*- Mode: C; tab-width: 4 -*-
3 * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 Change History (most recent first):
19 $Log: ConfigPropertySheet.cpp,v $
20 Revision 1.7 2009/07/01 19:20:37 herscher
21 <rdar://problem/6713286> UI changes for configuring sleep proxy settings.
23 Revision 1.6 2009/03/30 19:57:45 herscher
24 <rdar://problem/5925472> Current Bonjour code does not compile on Windows
25 <rdar://problem/5187308> Move build train to Visual Studio 2005
27 Revision 1.5 2006/08/14 23:25:28 cheshire
28 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
30 Revision 1.4 2005/10/05 20:46:50 herscher
31 <rdar://problem/4192011> Move Wide-Area preferences to another part of the registry so they don't removed during an update-install.
33 Revision 1.3 2005/03/03 19:55:22 shersche
34 <rdar://problem/4034481> ControlPanel source code isn't saving CVS log info
39 #include "ConfigPropertySheet.h"
40 #include <WinServices.h>
45 #define WM_DATAREADY ( WM_USER + 0x100 )
46 #define WM_REGISTRYCHANGED ( WM_USER + 0x101 )
49 IMPLEMENT_DYNCREATE(CConfigPropertySheet
, CPropertySheet
)
52 //---------------------------------------------------------------------------------------------------------------------------
53 // CConfigPropertySheet::CConfigPropertySheet
54 //---------------------------------------------------------------------------------------------------------------------------
56 CConfigPropertySheet::CConfigPropertySheet()
59 m_browseDomainsRef( NULL
),
60 m_regDomainsRef( NULL
),
62 m_threadExited( NULL
)
64 AddPage(&m_firstPage
);
65 AddPage(&m_secondPage
);
66 AddPage(&m_thirdPage
);
67 AddPage(&m_fourthPage
);
69 InitializeCriticalSection( &m_lock
);
73 //---------------------------------------------------------------------------------------------------------------------------
74 // CConfigPropertySheet::~CConfigPropertySheet
75 //---------------------------------------------------------------------------------------------------------------------------
77 CConfigPropertySheet::~CConfigPropertySheet()
79 DeleteCriticalSection( &m_lock
);
83 BEGIN_MESSAGE_MAP(CConfigPropertySheet
, CPropertySheet
)
84 //{{AFX_MSG_MAP(CConfigPropertySheet)
86 ON_MESSAGE( WM_DATAREADY
, OnDataReady
)
87 ON_MESSAGE( WM_REGISTRYCHANGED
, OnRegistryChanged
)
91 //---------------------------------------------------------------------------------------------------------------------------
92 // CConfigPropertySheet::OnInitDialog
93 //---------------------------------------------------------------------------------------------------------------------------
96 CConfigPropertySheet::OnInitDialog()
100 BOOL b
= CPropertySheet::OnInitDialog();
102 err
= SetupBrowsing();
103 require_noerr( err
, exit
);
105 err
= SetupRegistryNotifications();
106 require_noerr( err
, exit
);
114 //---------------------------------------------------------------------------------------------------------------------------
115 // CConfigPropertySheet::OnCommand
116 //---------------------------------------------------------------------------------------------------------------------------
119 CConfigPropertySheet::OnCommand(WPARAM wParam
, LPARAM lParam
)
121 // Check if OK or Cancel was hit
123 if ( ( wParam
== ID_WIZFINISH
) || ( wParam
== IDOK
) || ( wParam
== IDCANCEL
) )
128 return CPropertySheet::OnCommand(wParam
, lParam
);
132 //---------------------------------------------------------------------------------------------------------------------------
133 // CConfigPropertySheet::OnDataReady
134 //---------------------------------------------------------------------------------------------------------------------------
137 CConfigPropertySheet::OnDataReady(WPARAM inWParam
, LPARAM inLParam
)
139 if (WSAGETSELECTERROR(inLParam
) && !(HIWORD(inLParam
)))
141 dlog( kDebugLevelError
, "OnSocket: window error\n" );
145 SOCKET sock
= (SOCKET
) inWParam
;
147 if ( m_browseDomainsRef
&& DNSServiceRefSockFD( m_browseDomainsRef
) == (int) sock
)
149 DNSServiceProcessResult( m_browseDomainsRef
);
151 else if ( m_regDomainsRef
&& DNSServiceRefSockFD( m_regDomainsRef
) == (int) sock
)
153 DNSServiceProcessResult( m_regDomainsRef
);
161 //---------------------------------------------------------------------------------------------------------------------------
162 // CConfigPropertySheet::OnRegistryChanged
163 //---------------------------------------------------------------------------------------------------------------------------
166 CConfigPropertySheet::OnRegistryChanged( WPARAM inWParam
, LPARAM inLParam
)
168 DEBUG_UNUSED( inWParam
);
169 DEBUG_UNUSED( inLParam
);
171 if ( GetActivePage() == &m_firstPage
)
173 m_firstPage
.OnRegistryChanged();
180 //---------------------------------------------------------------------------------------------------------------------------
181 // CConfigPropertySheet::OnEndDialog
182 //---------------------------------------------------------------------------------------------------------------------------
185 CConfigPropertySheet::OnEndDialog()
189 err
= TearDownRegistryNotifications();
192 err
= TearDownBrowsing();
197 //---------------------------------------------------------------------------------------------------------------------------
198 // CConfigPropertySheet::SetupBrowsing
199 //---------------------------------------------------------------------------------------------------------------------------
202 CConfigPropertySheet::SetupBrowsing()
206 // Start browsing for browse domains
208 err
= DNSServiceEnumerateDomains( &m_browseDomainsRef
, kDNSServiceFlagsBrowseDomains
, 0, BrowseDomainsReply
, this );
209 require_noerr( err
, exit
);
211 err
= WSAAsyncSelect( DNSServiceRefSockFD( m_browseDomainsRef
), m_hWnd
, WM_DATAREADY
, FD_READ
|FD_CLOSE
);
212 require_noerr( err
, exit
);
214 // Start browsing for registration domains
216 err
= DNSServiceEnumerateDomains( &m_regDomainsRef
, kDNSServiceFlagsRegistrationDomains
, 0, RegDomainsReply
, this );
217 require_noerr( err
, exit
);
219 err
= WSAAsyncSelect( DNSServiceRefSockFD( m_regDomainsRef
), m_hWnd
, WM_DATAREADY
, FD_READ
|FD_CLOSE
);
220 require_noerr( err
, exit
);
233 //---------------------------------------------------------------------------------------------------------------------------
234 // CConfigPropertySheet::TearDownBrowsing
235 //---------------------------------------------------------------------------------------------------------------------------
238 CConfigPropertySheet::TearDownBrowsing()
240 OSStatus err
= kNoErr
;
242 if ( m_browseDomainsRef
)
244 err
= WSAAsyncSelect( DNSServiceRefSockFD( m_browseDomainsRef
), m_hWnd
, 0, 0 );
247 DNSServiceRefDeallocate( m_browseDomainsRef
);
249 m_browseDomainsRef
= NULL
;
252 if ( m_regDomainsRef
)
254 err
= WSAAsyncSelect( DNSServiceRefSockFD( m_regDomainsRef
), m_hWnd
, 0, 0 );
257 DNSServiceRefDeallocate( m_regDomainsRef
);
259 m_regDomainsRef
= NULL
;
266 //---------------------------------------------------------------------------------------------------------------------------
267 // CConfigPropertySheet::SetupRegistryNotifications
268 //---------------------------------------------------------------------------------------------------------------------------
271 CConfigPropertySheet::SetupRegistryNotifications()
273 unsigned int threadId
;
276 check( m_threadExited
== NULL
);
277 check( m_thread
== NULL
);
279 err
= RegCreateKey( HKEY_LOCAL_MACHINE
, kServiceParametersNode L
"\\DynDNS\\State\\Hostnames", &m_statusKey
);
280 require_noerr( err
, exit
);
282 m_threadExited
= CreateEvent( NULL
, FALSE
, FALSE
, NULL
);
283 err
= translate_errno( m_threadExited
, (OSStatus
) GetLastError(), kUnknownErr
);
284 require_noerr( err
, exit
);
286 // Create thread with _beginthreadex() instead of CreateThread() to avoid memory leaks when using static run-time
287 // libraries. See <http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/createthread.asp>.
289 m_thread
= (HANDLE
) _beginthreadex_compat( NULL
, 0, WatchRegistry
, this, 0, &threadId
);
290 err
= translate_errno( m_thread
, (OSStatus
) GetLastError(), kUnknownErr
);
291 require_noerr( err
, exit
);
297 TearDownRegistryNotifications();
304 //---------------------------------------------------------------------------------------------------------------------------
305 // CConfigPropertySheet::TearDownRegistryNotifications
306 //---------------------------------------------------------------------------------------------------------------------------
309 CConfigPropertySheet::TearDownRegistryNotifications()
311 OSStatus err
= kNoErr
;
315 EnterCriticalSection( &m_lock
);
317 RegCloseKey( m_statusKey
);
320 LeaveCriticalSection( &m_lock
);
323 if ( m_threadExited
)
325 err
= WaitForSingleObject( m_threadExited
, 5 * 1000 );
326 require_noerr( err
, exit
);
331 if ( m_threadExited
)
333 CloseHandle( m_threadExited
);
334 m_threadExited
= NULL
;
339 CloseHandle( m_thread
);
347 //---------------------------------------------------------------------------------------------------------------------------
348 // CConfigPropertySheet::DecodeDomainName
349 //---------------------------------------------------------------------------------------------------------------------------
352 CConfigPropertySheet::DecodeDomainName( const char * raw
, CString
& decoded
)
354 char nextLabel
[128] = "\0";
355 char decodedDomainString
[kDNSServiceMaxDomainName
];
356 char * buffer
= (char *) raw
;
359 const char *label
[128];
364 decodedDomainString
[0] = '\0';
370 label
[labels
++] = buffer
;
371 buffer
= (char *) GetNextLabel(buffer
, text
);
374 buffer
= (char*) raw
;
376 for (i
= 0; i
< labels
; i
++)
378 buffer
= (char *)GetNextLabel(buffer
, nextLabel
);
379 strcat(decodedDomainString
, nextLabel
);
380 strcat(decodedDomainString
, ".");
383 // Remove trailing dot from domain name.
385 decodedDomainString
[ strlen( decodedDomainString
) - 1 ] = '\0';
387 // Convert to Unicode
389 err
= UTF8StringToStringObject( decodedDomainString
, decoded
);
395 //---------------------------------------------------------------------------------------------------------------------------
396 // CConfigPropertySheet::GetNextLabel
397 //---------------------------------------------------------------------------------------------------------------------------
400 CConfigPropertySheet::GetNextLabel( const char * cstr
, char label
[64] )
403 while (*cstr
&& *cstr
!= '.') // While we have characters in the label...
409 if (isdigit(cstr
[-1]) && isdigit(cstr
[0]) && isdigit(cstr
[1]))
411 int v0
= cstr
[-1] - '0'; // then interpret as three-digit decimal
412 int v1
= cstr
[ 0] - '0';
413 int v2
= cstr
[ 1] - '0';
414 int val
= v0
* 100 + v1
* 10 + v2
;
415 if (val
<= 255) { c
= (char)val
; cstr
+= 2; } // If valid three-digit decimal value, use it
419 if (ptr
>= label
+64) return(NULL
);
421 if (*cstr
) cstr
++; // Skip over the trailing dot (if present)
427 //---------------------------------------------------------------------------------------------------------------------------
428 // CConfigPropertySheet::BrowseDomainsReply
429 //---------------------------------------------------------------------------------------------------------------------------
432 CConfigPropertySheet::BrowseDomainsReply
435 DNSServiceFlags flags
,
436 uint32_t interfaceIndex
,
437 DNSServiceErrorType errorCode
,
438 const char * replyDomain
,
442 CConfigPropertySheet
* self
= reinterpret_cast<CConfigPropertySheet
*>(context
);
446 DEBUG_UNUSED( sdRef
);
447 DEBUG_UNUSED( interfaceIndex
);
454 check( replyDomain
);
456 // Ignore local domains
458 if ( strcmp( replyDomain
, "local." ) == 0 )
465 err
= self
->DecodeDomainName( replyDomain
, decoded
);
466 require_noerr( err
, exit
);
468 // Remove trailing '.'
470 decoded
.TrimRight( '.' );
472 if ( flags
& kDNSServiceFlagsAdd
)
474 self
->m_browseDomains
.push_back( decoded
);
478 self
->m_browseDomains
.remove( decoded
);
487 //---------------------------------------------------------------------------------------------------------------------------
488 // CConfigPropertySheet::RegDomainsReply
489 //---------------------------------------------------------------------------------------------------------------------------
492 CConfigPropertySheet::RegDomainsReply
495 DNSServiceFlags flags
,
496 uint32_t interfaceIndex
,
497 DNSServiceErrorType errorCode
,
498 const char * replyDomain
,
502 CConfigPropertySheet
* self
= reinterpret_cast<CConfigPropertySheet
*>(context
);
506 DEBUG_UNUSED( sdRef
);
507 DEBUG_UNUSED( interfaceIndex
);
514 check( replyDomain
);
516 // Ignore local domains
518 if ( strcmp( replyDomain
, "local." ) == 0 )
523 err
= self
->DecodeDomainName( replyDomain
, decoded
);
524 require_noerr( err
, exit
);
526 // Remove trailing '.'
528 decoded
.TrimRight( '.' );
530 if ( flags
& kDNSServiceFlagsAdd
)
532 if ( self
->GetActivePage() == &self
->m_secondPage
)
534 self
->m_secondPage
.OnAddRegistrationDomain( decoded
);
537 self
->m_regDomains
.push_back( decoded
);
541 if ( self
->GetActivePage() == &self
->m_secondPage
)
543 self
->m_secondPage
.OnRemoveRegistrationDomain( decoded
);
546 self
->m_regDomains
.remove( decoded
);
555 //---------------------------------------------------------------------------------------------------------------------------
556 // CConfigPropertySheet::WatchRegistry
557 //---------------------------------------------------------------------------------------------------------------------------
560 CConfigPropertySheet::WatchRegistry ( LPVOID inParam
)
564 CConfigPropertySheet
* self
= reinterpret_cast<CConfigPropertySheet
*>(inParam
);
569 RegNotifyChangeKeyValue( self
->m_statusKey
, TRUE
, REG_NOTIFY_CHANGE_LAST_SET
, NULL
, FALSE
);
571 EnterCriticalSection( &self
->m_lock
);
573 done
= ( self
->m_statusKey
== NULL
) ? true : false;
577 self
->PostMessage( WM_REGISTRYCHANGED
, 0, 0 );
580 LeaveCriticalSection( &self
->m_lock
);
583 SetEvent( self
->m_threadExited
);