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 "ConfigPropertySheet.h"
19#include <WinServices.h>
20extern "C"
21{
22#include <ClientCommon.h>
23}
24#include <process.h>
25
26// Custom events
27
28#define WM_DATAREADY		( WM_USER + 0x100 )
29
30
31IMPLEMENT_DYNCREATE(CConfigPropertySheet, CPropertySheet)
32
33
34//---------------------------------------------------------------------------------------------------------------------------
35//	CConfigPropertySheet::CConfigPropertySheet
36//---------------------------------------------------------------------------------------------------------------------------
37
38CConfigPropertySheet::CConfigPropertySheet()
39:
40	CPropertySheet(),
41	m_browseDomainsRef( NULL ),
42	m_thread( NULL ),
43	m_threadExited( NULL )
44{
45	AddPage(&m_firstPage );
46	AddPage(&m_secondPage);
47	AddPage(&m_thirdPage);
48
49	InitializeCriticalSection( &m_lock );
50}
51
52
53//---------------------------------------------------------------------------------------------------------------------------
54//	CConfigPropertySheet::~CConfigPropertySheet
55//---------------------------------------------------------------------------------------------------------------------------
56
57CConfigPropertySheet::~CConfigPropertySheet()
58{
59	DeleteCriticalSection( &m_lock );
60}
61
62
63BEGIN_MESSAGE_MAP(CConfigPropertySheet, CPropertySheet)
64	//{{AFX_MSG_MAP(CConfigPropertySheet)
65	//}}AFX_MSG_MAP
66	ON_MESSAGE( WM_DATAREADY, OnDataReady )
67END_MESSAGE_MAP()
68
69
70//---------------------------------------------------------------------------------------------------------------------------
71//	CConfigPropertySheet::OnInitDialog
72//---------------------------------------------------------------------------------------------------------------------------
73
74BOOL
75CConfigPropertySheet::OnInitDialog()
76{
77	OSStatus err;
78
79	BOOL b = CPropertySheet::OnInitDialog();
80
81	err = SetupBrowsing();
82	require_noerr( err, exit );
83
84exit:
85
86	return b;
87}
88
89
90//---------------------------------------------------------------------------------------------------------------------------
91//	CConfigPropertySheet::OnCommand
92//---------------------------------------------------------------------------------------------------------------------------
93
94BOOL
95CConfigPropertySheet::OnCommand(WPARAM wParam, LPARAM lParam)
96{
97   // Check if OK or Cancel was hit
98
99   if ( ( wParam == ID_WIZFINISH ) || ( wParam == IDOK ) || ( wParam == IDCANCEL ) )
100   {
101      OnEndDialog();
102   }
103
104   return CPropertySheet::OnCommand(wParam, lParam);
105}
106
107
108//---------------------------------------------------------------------------------------------------------------------------
109//	CConfigPropertySheet::OnDataReady
110//---------------------------------------------------------------------------------------------------------------------------
111
112LRESULT
113CConfigPropertySheet::OnDataReady(WPARAM inWParam, LPARAM inLParam)
114{
115	if (WSAGETSELECTERROR(inLParam) && !(HIWORD(inLParam)))
116	{
117		dlog( kDebugLevelError, "OnSocket: window error\n" );
118	}
119	else
120	{
121		SOCKET sock = (SOCKET) inWParam;
122
123		if ( m_browseDomainsRef && DNSServiceRefSockFD( m_browseDomainsRef ) == (int) sock )
124		{
125			DNSServiceProcessResult( m_browseDomainsRef );
126		}
127	}
128
129	return 0;
130}
131
132
133//---------------------------------------------------------------------------------------------------------------------------
134//	CConfigPropertySheet::OnEndDialog
135//---------------------------------------------------------------------------------------------------------------------------
136
137void
138CConfigPropertySheet::OnEndDialog()
139{
140	OSStatus err;
141
142	err = TearDownBrowsing();
143	check_noerr( err );
144}
145
146
147//---------------------------------------------------------------------------------------------------------------------------
148//	CConfigPropertySheet::SetupBrowsing
149//---------------------------------------------------------------------------------------------------------------------------
150
151OSStatus
152CConfigPropertySheet::SetupBrowsing()
153{
154	OSStatus err;
155
156	// Start browsing for browse domains
157
158	err = DNSServiceEnumerateDomains( &m_browseDomainsRef, kDNSServiceFlagsBrowseDomains, 0, BrowseDomainsReply, this );
159	require_noerr( err, exit );
160
161	err = WSAAsyncSelect( DNSServiceRefSockFD( m_browseDomainsRef ), m_hWnd, WM_DATAREADY, FD_READ|FD_CLOSE );
162	require_noerr( err, exit );
163
164exit:
165
166	if ( err )
167	{
168		TearDownBrowsing();
169	}
170
171	return err;
172}
173
174
175//---------------------------------------------------------------------------------------------------------------------------
176//	CConfigPropertySheet::TearDownBrowsing
177//---------------------------------------------------------------------------------------------------------------------------
178
179OSStatus
180CConfigPropertySheet::TearDownBrowsing()
181{
182	OSStatus err = kNoErr;
183
184	if ( m_browseDomainsRef )
185	{
186		err = WSAAsyncSelect( DNSServiceRefSockFD( m_browseDomainsRef ), m_hWnd, 0, 0 );
187		check_noerr( err );
188
189		DNSServiceRefDeallocate( m_browseDomainsRef );
190
191		m_browseDomainsRef = NULL;
192	}
193
194	return err;
195}
196
197
198//---------------------------------------------------------------------------------------------------------------------------
199//	CConfigPropertySheet::DecodeDomainName
200//---------------------------------------------------------------------------------------------------------------------------
201
202OSStatus
203CConfigPropertySheet::DecodeDomainName( const char * raw, CString & decoded )
204{
205	char nextLabel[128] = "\0";
206	char decodedDomainString[kDNSServiceMaxDomainName];
207    char * buffer = (char *) raw;
208    int labels = 0, i;
209    char text[64];
210	const char *label[128];
211	OSStatus	err;
212
213	// Initialize
214
215	decodedDomainString[0] = '\0';
216
217    // Count the labels
218
219	while ( *buffer )
220	{
221		label[labels++] = buffer;
222		buffer = (char *) GetNextLabel(buffer, text);
223    }
224
225    buffer = (char*) raw;
226
227    for (i = 0; i < labels; i++)
228	{
229		buffer = (char *)GetNextLabel(buffer, nextLabel);
230        strcat(decodedDomainString, nextLabel);
231        strcat(decodedDomainString, ".");
232    }
233
234    // Remove trailing dot from domain name.
235
236	decodedDomainString[ strlen( decodedDomainString ) - 1 ] = '\0';
237
238	// Convert to Unicode
239
240	err = UTF8StringToStringObject( decodedDomainString, decoded );
241
242	return err;
243}
244
245
246//---------------------------------------------------------------------------------------------------------------------------
247//	CConfigPropertySheet::BrowseDomainsReply
248//---------------------------------------------------------------------------------------------------------------------------
249
250void DNSSD_API
251CConfigPropertySheet::BrowseDomainsReply
252							(
253							DNSServiceRef			sdRef,
254							DNSServiceFlags			flags,
255							uint32_t				interfaceIndex,
256							DNSServiceErrorType		errorCode,
257							const char			*	replyDomain,
258							void				*	context
259							)
260{
261	CConfigPropertySheet	*	self = reinterpret_cast<CConfigPropertySheet*>(context);
262	CString						decoded;
263	OSStatus					err;
264
265	DEBUG_UNUSED( sdRef );
266	DEBUG_UNUSED( interfaceIndex );
267
268	if ( errorCode )
269	{
270		goto exit;
271	}
272
273	check( replyDomain );
274
275	// Ignore local domains
276
277	if ( strcmp( replyDomain, "local." ) == 0 )
278	{
279		goto exit;
280	}
281
282	err = self->DecodeDomainName( replyDomain, decoded );
283	require_noerr( err, exit );
284
285	// Remove trailing '.'
286
287	decoded.TrimRight( '.' );
288
289	if ( flags & kDNSServiceFlagsAdd )
290	{
291		self->m_browseDomains.push_back( decoded );
292	}
293	else
294	{
295		self->m_browseDomains.remove( decoded );
296	}
297
298exit:
299
300	return;
301}
302