/* -*- 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 "ConfigPropertySheet.h" #include <WinServices.h> extern "C" { #include <ClientCommon.h> } #include <process.h> // Custom events #define WM_DATAREADY ( WM_USER + 0x100 ) IMPLEMENT_DYNCREATE(CConfigPropertySheet, CPropertySheet) //--------------------------------------------------------------------------------------------------------------------------- // CConfigPropertySheet::CConfigPropertySheet //--------------------------------------------------------------------------------------------------------------------------- CConfigPropertySheet::CConfigPropertySheet() : CPropertySheet(), m_browseDomainsRef( NULL ), m_thread( NULL ), m_threadExited( NULL ) { AddPage(&m_firstPage ); AddPage(&m_secondPage); AddPage(&m_thirdPage); InitializeCriticalSection( &m_lock ); } //--------------------------------------------------------------------------------------------------------------------------- // CConfigPropertySheet::~CConfigPropertySheet //--------------------------------------------------------------------------------------------------------------------------- CConfigPropertySheet::~CConfigPropertySheet() { DeleteCriticalSection( &m_lock ); } BEGIN_MESSAGE_MAP(CConfigPropertySheet, CPropertySheet) //{{AFX_MSG_MAP(CConfigPropertySheet) //}}AFX_MSG_MAP ON_MESSAGE( WM_DATAREADY, OnDataReady ) END_MESSAGE_MAP() //--------------------------------------------------------------------------------------------------------------------------- // CConfigPropertySheet::OnInitDialog //--------------------------------------------------------------------------------------------------------------------------- BOOL CConfigPropertySheet::OnInitDialog() { OSStatus err; BOOL b = CPropertySheet::OnInitDialog(); err = SetupBrowsing(); require_noerr( err, exit ); exit: return b; } //--------------------------------------------------------------------------------------------------------------------------- // CConfigPropertySheet::OnCommand //--------------------------------------------------------------------------------------------------------------------------- BOOL CConfigPropertySheet::OnCommand(WPARAM wParam, LPARAM lParam) { // Check if OK or Cancel was hit if ( ( wParam == ID_WIZFINISH ) || ( wParam == IDOK ) || ( wParam == IDCANCEL ) ) { OnEndDialog(); } return CPropertySheet::OnCommand(wParam, lParam); } //--------------------------------------------------------------------------------------------------------------------------- // CConfigPropertySheet::OnDataReady //--------------------------------------------------------------------------------------------------------------------------- LRESULT CConfigPropertySheet::OnDataReady(WPARAM inWParam, LPARAM inLParam) { if (WSAGETSELECTERROR(inLParam) && !(HIWORD(inLParam))) { dlog( kDebugLevelError, "OnSocket: window error\n" ); } else { SOCKET sock = (SOCKET) inWParam; if ( m_browseDomainsRef && DNSServiceRefSockFD( m_browseDomainsRef ) == (int) sock ) { DNSServiceProcessResult( m_browseDomainsRef ); } } return 0; } //--------------------------------------------------------------------------------------------------------------------------- // CConfigPropertySheet::OnEndDialog //--------------------------------------------------------------------------------------------------------------------------- void CConfigPropertySheet::OnEndDialog() { OSStatus err; err = TearDownBrowsing(); check_noerr( err ); } //--------------------------------------------------------------------------------------------------------------------------- // CConfigPropertySheet::SetupBrowsing //--------------------------------------------------------------------------------------------------------------------------- OSStatus CConfigPropertySheet::SetupBrowsing() { OSStatus err; // Start browsing for browse domains err = DNSServiceEnumerateDomains( &m_browseDomainsRef, kDNSServiceFlagsBrowseDomains, 0, BrowseDomainsReply, this ); require_noerr( err, exit ); err = WSAAsyncSelect( DNSServiceRefSockFD( m_browseDomainsRef ), m_hWnd, WM_DATAREADY, FD_READ|FD_CLOSE ); require_noerr( err, exit ); exit: if ( err ) { TearDownBrowsing(); } return err; } //--------------------------------------------------------------------------------------------------------------------------- // CConfigPropertySheet::TearDownBrowsing //--------------------------------------------------------------------------------------------------------------------------- OSStatus CConfigPropertySheet::TearDownBrowsing() { OSStatus err = kNoErr; if ( m_browseDomainsRef ) { err = WSAAsyncSelect( DNSServiceRefSockFD( m_browseDomainsRef ), m_hWnd, 0, 0 ); check_noerr( err ); DNSServiceRefDeallocate( m_browseDomainsRef ); m_browseDomainsRef = NULL; } return err; } //--------------------------------------------------------------------------------------------------------------------------- // CConfigPropertySheet::DecodeDomainName //--------------------------------------------------------------------------------------------------------------------------- OSStatus CConfigPropertySheet::DecodeDomainName( const char * raw, CString & decoded ) { char nextLabel[128] = "\0"; char decodedDomainString[kDNSServiceMaxDomainName]; char * buffer = (char *) raw; int labels = 0, i; char text[64]; const char *label[128]; OSStatus err; // Initialize decodedDomainString[0] = '\0'; // Count the labels while ( *buffer ) { label[labels++] = buffer; buffer = (char *) GetNextLabel(buffer, text); } buffer = (char*) raw; for (i = 0; i < labels; i++) { buffer = (char *)GetNextLabel(buffer, nextLabel); strcat(decodedDomainString, nextLabel); strcat(decodedDomainString, "."); } // Remove trailing dot from domain name. decodedDomainString[ strlen( decodedDomainString ) - 1 ] = '\0'; // Convert to Unicode err = UTF8StringToStringObject( decodedDomainString, decoded ); return err; } //--------------------------------------------------------------------------------------------------------------------------- // CConfigPropertySheet::BrowseDomainsReply //--------------------------------------------------------------------------------------------------------------------------- void DNSSD_API CConfigPropertySheet::BrowseDomainsReply ( DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char * replyDomain, void * context ) { CConfigPropertySheet * self = reinterpret_cast<CConfigPropertySheet*>(context); CString decoded; OSStatus err; DEBUG_UNUSED( sdRef ); DEBUG_UNUSED( interfaceIndex ); if ( errorCode ) { goto exit; } check( replyDomain ); // Ignore local domains if ( strcmp( replyDomain, "local." ) == 0 ) { goto exit; } err = self->DecodeDomainName( replyDomain, decoded ); require_noerr( err, exit ); // Remove trailing '.' decoded.TrimRight( '.' ); if ( flags & kDNSServiceFlagsAdd ) { self->m_browseDomains.push_back( decoded ); } else { self->m_browseDomains.remove( decoded ); } exit: return; }