• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /macosx-10.9.5/mDNSResponder-522.92.1/mDNSWindows/DNSServiceBrowser/WindowsCE/Sources/
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	"stdafx.h"
19
20#include	"Application.h"
21
22#include	"DNSServices.h"
23
24#include	"BrowserDialog.h"
25
26#ifdef _DEBUG
27#define new DEBUG_NEW
28#undef THIS_FILE
29static char THIS_FILE[] = __FILE__;
30#endif
31
32//===========================================================================================================================
33//	Constants
34//===========================================================================================================================
35
36#define	WM_USER_SERVICE_ADD			( WM_USER + 0x100 )
37#define	WM_USER_SERVICE_REMOVE		( WM_USER + 0x101 )
38
39//===========================================================================================================================
40//	Message Map
41//===========================================================================================================================
42
43BEGIN_MESSAGE_MAP(BrowserDialog, CDialog)
44	//{{AFX_MSG_MAP(BrowserDialog)
45	ON_NOTIFY(NM_CLICK, IDC_BROWSE_LIST, OnBrowserListDoubleClick)
46	ON_MESSAGE( WM_USER_SERVICE_ADD, OnServiceAdd )
47	ON_MESSAGE( WM_USER_SERVICE_REMOVE, OnServiceRemove )
48	//}}AFX_MSG_MAP
49END_MESSAGE_MAP()
50
51static DWORD	UTF8StringToStringObject( const char *inUTF8, CString &inObject );
52
53//===========================================================================================================================
54//	BrowserDialog
55//===========================================================================================================================
56
57BrowserDialog::BrowserDialog( CWnd *inParent )
58	: CDialog( BrowserDialog::IDD, inParent )
59{
60	//{{AFX_DATA_INIT(BrowserDialog)
61		// Note: the ClassWizard will add member initialization here
62	//}}AFX_DATA_INIT
63
64	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32.
65
66	mIcon = AfxGetApp()->LoadIcon( IDR_MAINFRAME );
67	ASSERT( mIcon );
68}
69
70//===========================================================================================================================
71//	DoDataExchange
72//===========================================================================================================================
73
74void	BrowserDialog::DoDataExchange( CDataExchange *pDX )
75{
76	CDialog::DoDataExchange(pDX);
77	//{{AFX_DATA_MAP(BrowserDialog)
78	DDX_Control(pDX, IDC_BROWSE_LIST, mBrowserList);
79	//}}AFX_DATA_MAP
80}
81
82//===========================================================================================================================
83//	OnInitDialog
84//===========================================================================================================================
85
86BOOL	BrowserDialog::OnInitDialog()
87{
88	CString		s;
89
90	CDialog::OnInitDialog();
91
92	// Set the icon for this dialog. The framework does this automatically when the application's main window is not a dialog.
93
94	SetIcon( mIcon, TRUE );		// Set big icon
95	SetIcon( mIcon, FALSE );	// Set small icon
96
97	CenterWindow( GetDesktopWindow() );
98
99	// Set up the list.
100
101	CRect		rect;
102
103	s.LoadString( IDS_BROWSER_LIST_COLUMN_NAME );
104	mBrowserList.GetWindowRect( rect );
105	mBrowserList.InsertColumn( 0, s, LVCFMT_LEFT, rect.Width() - 8 );
106
107	// Start browsing for services.
108
109	DNSStatus		err;
110
111	err = DNSBrowserCreate( 0, OnBrowserCallBack, this, &mBrowser );
112	if( err )
113	{
114		AfxMessageBox( IDP_SOCKETS_INIT_FAILED );
115		goto exit;
116	}
117
118	err = DNSBrowserStartServiceSearch( mBrowser, kDNSBrowserFlagAutoResolve, "_http._tcp", NULL );
119	if( err )
120	{
121		AfxMessageBox( IDP_SOCKETS_INIT_FAILED );
122		goto exit;
123	}
124
125exit:
126	return( TRUE );
127}
128
129
130//===========================================================================================================================
131//	OnBrowserListDoubleClick
132//===========================================================================================================================
133
134void	BrowserDialog::OnBrowserListDoubleClick( NMHDR *pNMHDR, LRESULT *pResult )
135{
136	int		selectedItem;
137
138	(void) pNMHDR;	// Unused
139
140	selectedItem = mBrowserList.GetNextItem( -1, LVNI_SELECTED );
141	if( selectedItem >= 0 )
142	{
143		BrowserEntry *		entry;
144		CString				temp;
145		CString				url;
146
147		// Build the URL from the IP and optional TXT record.
148
149		entry = &mBrowserEntries[ selectedItem ];
150		url += "http://" + entry->ip;
151		temp = entry->text;
152		if( temp.Find( TEXT( "path=" ) ) == 0 )
153		{
154			temp.Delete( 0, 5 );
155		}
156		if( temp.Find( '/' ) != 0 )
157		{
158			url += '/';
159		}
160		url += temp;
161
162		// Let the system open the URL in the correct app.
163
164		SHELLEXECUTEINFO		info;
165
166		info.cbSize			= sizeof( info );
167		info.fMask 			= 0;
168		info.hwnd 			= NULL;
169		info.lpVerb 		= NULL;
170		info.lpFile 		= url;
171		info.lpParameters 	= NULL;
172		info.lpDirectory 	= NULL;
173		info.nShow 			= SW_SHOWNORMAL;
174		info.hInstApp 		= NULL;
175
176		ShellExecuteEx( &info );
177	}
178	*pResult = 0;
179}
180
181//===========================================================================================================================
182//	OnBrowserCallBack [static]
183//===========================================================================================================================
184
185void
186	BrowserDialog::OnBrowserCallBack(
187		void *					inContext,
188		DNSBrowserRef			inRef,
189		DNSStatus				inStatusCode,
190		const DNSBrowserEvent *	inEvent )
191{
192	BrowserDialog *		dialog;
193	BrowserEntry *		entry;
194	BOOL				posted;
195
196	DNS_UNUSED( inStatusCode );
197	dialog = reinterpret_cast < BrowserDialog * > ( inContext );
198	ASSERT( dialog );
199
200	switch( inEvent->type )
201	{
202		case kDNSBrowserEventTypeResolved:
203			if( inEvent->data.resolved->address.addressType == kDNSNetworkAddressTypeIPv4  )
204			{
205				char		ip[ 64 ];
206
207				sprintf( ip, "%u.%u.%u.%u:%u",
208					inEvent->data.resolved->address.u.ipv4.addr.v8[ 0 ],
209					inEvent->data.resolved->address.u.ipv4.addr.v8[ 1 ],
210					inEvent->data.resolved->address.u.ipv4.addr.v8[ 2 ],
211					inEvent->data.resolved->address.u.ipv4.addr.v8[ 3 ],
212					( inEvent->data.resolved->address.u.ipv4.port.v8[ 0 ] << 8 ) |
213					  inEvent->data.resolved->address.u.ipv4.port.v8[ 1 ] );
214
215				entry = new BrowserEntry;
216				ASSERT( entry );
217				if( entry )
218				{
219					UTF8StringToStringObject( inEvent->data.resolved->name, entry->name );
220					UTF8StringToStringObject( ip, entry->ip );
221					UTF8StringToStringObject( inEvent->data.resolved->textRecord, entry->text );
222
223					posted = ::PostMessage( dialog->GetSafeHwnd(), WM_USER_SERVICE_ADD, 0, (LPARAM) entry );
224					ASSERT( posted );
225					if( !posted )
226					{
227						delete entry;
228					}
229				}
230			}
231			break;
232
233		case kDNSBrowserEventTypeRemoveService:
234			entry = new BrowserEntry;
235			ASSERT( entry );
236			if( entry )
237			{
238				UTF8StringToStringObject( inEvent->data.removeService.name, entry->name );
239
240				posted = ::PostMessage( dialog->GetSafeHwnd(), WM_USER_SERVICE_REMOVE, 0, (LPARAM) entry );
241				ASSERT( posted );
242				if( !posted )
243				{
244					delete entry;
245				}
246			}
247			break;
248
249		default:
250			break;
251	}
252}
253
254//===========================================================================================================================
255//	BrowserAddService
256//===========================================================================================================================
257
258LONG	BrowserDialog::OnServiceAdd( WPARAM inWParam, LPARAM inLParam )
259{
260	BrowserEntry *		entry;
261	INT_PTR				lo;
262	INT_PTR				hi;
263	INT_PTR				mid;
264	int					result;
265
266	(void) inWParam;	// Unused
267
268	entry = reinterpret_cast < BrowserEntry * > ( inLParam );
269	ASSERT( entry );
270
271	result 	= -1;
272	mid		= 0;
273	lo 		= 0;
274	hi 		= mBrowserEntries.GetSize() - 1;
275	while( lo <= hi )
276	{
277		mid = ( lo + hi ) / 2;
278		result = entry->name.CompareNoCase( mBrowserEntries[ mid ].name );
279		if( result == 0 )
280		{
281			break;
282		}
283		else if( result < 0 )
284		{
285			hi = mid - 1;
286		}
287		else
288		{
289			lo = mid + 1;
290		}
291	}
292	if( result == 0 )
293	{
294		mBrowserEntries[ mid ].ip	= entry->ip;
295		mBrowserEntries[ mid ].text	= entry->text;
296	}
297	else
298	{
299		if( result > 0 )
300		{
301			mid += 1;
302		}
303		mBrowserEntries.InsertAt( mid, *entry );
304		mBrowserList.InsertItem( mid, entry->name );
305	}
306	delete entry;
307	return( 0 );
308}
309
310//===========================================================================================================================
311//	OnServiceRemove
312//===========================================================================================================================
313
314LONG	BrowserDialog::OnServiceRemove( WPARAM inWParam, LPARAM inLParam )
315{
316	BrowserEntry *		entry;
317	INT_PTR				hi;
318	INT_PTR				lo;
319	INT_PTR				mid;
320	int					result;
321
322	(void) inWParam;	// Unused
323
324	entry = reinterpret_cast < BrowserEntry * > ( inLParam );
325	ASSERT( entry );
326
327	result 	= -1;
328	mid		= 0;
329	lo 		= 0;
330	hi 		= mBrowserEntries.GetSize() - 1;
331	while( lo <= hi )
332	{
333		mid = ( lo + hi ) / 2;
334		result = entry->name.CompareNoCase( mBrowserEntries[ mid ].name );
335		if( result == 0 )
336		{
337			break;
338		}
339		else if( result < 0 )
340		{
341			hi = mid - 1;
342		}
343		else
344		{
345			lo = mid + 1;
346		}
347	}
348	if( result == 0 )
349	{
350		mBrowserList.DeleteItem( mid );
351		mBrowserEntries.RemoveAt( mid );
352	}
353	delete entry;
354	return( 0 );
355}
356
357#if 0
358#pragma mark -
359#endif
360
361//===========================================================================================================================
362//	UTF8StringToStringObject
363//===========================================================================================================================
364
365static DWORD	UTF8StringToStringObject( const char *inUTF8, CString &inObject )
366{
367	DWORD			err;
368	int				n;
369	wchar_t *		unicode;
370
371	unicode = NULL;
372
373	n = MultiByteToWideChar( CP_UTF8, 0, inUTF8, -1, NULL, 0 );
374	if( n > 0 )
375	{
376		unicode = (wchar_t *) malloc( (size_t)( n * sizeof( wchar_t ) ) );
377		if( !unicode ) { err = ERROR_INSUFFICIENT_BUFFER; goto exit; };
378
379		n = MultiByteToWideChar( CP_UTF8, 0, inUTF8, -1, unicode, n );
380		inObject = unicode;
381	}
382	else
383	{
384		inObject = "";
385	}
386	err = 0;
387
388exit:
389	if( unicode )
390	{
391		free( unicode );
392	}
393	return( err );
394}
395