2 * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
25 Change History (most recent first):
27 $Log: ChooserDialog.cpp,v $
28 Revision 1.1 2003/08/21 02:06:47 bradley
29 Moved Rendezvous Browser for non-Windows CE into Windows sub-folder.
31 Revision 1.7 2003/08/20 06:45:56 bradley
32 Updated for IP address changes in DNSServices. Added support for browsing for Xserve RAID.
34 Revision 1.6 2003/08/12 19:56:28 cheshire
37 Revision 1.5 2003/07/13 01:03:55 cheshire
38 Diffs provided by Bob Bradley to provide provide proper display of Unicode names
40 Revision 1.4 2003/07/02 21:20:06 cheshire
41 <rdar://problem/3313413> Update copyright notices, etc., in source code comments
43 Revision 1.3 2002/09/21 20:44:55 zarzycki
46 Revision 1.2 2002/09/20 08:39:21 bradley
47 Make sure each resolved item matches the selected service type to handle resolved that may have
48 been queued up on the Windows Message Loop. Reduce column to fit when scrollbar is present.
50 Revision 1.1 2002/09/20 06:12:52 bradley
51 Rendezvous Browser for Windows
66 #include "DNSServices.h"
68 #include "Application.h"
69 #include "AboutDialog.h"
72 #include "ChooserDialog.h"
77 static char THIS_FILE
[] = __FILE__
;
81 #pragma mark == Constants ==
84 //===========================================================================================================================
86 //===========================================================================================================================
92 kChooserMenuIndexFile
= 0,
93 kChooserMenuIndexHelp
= 1
98 #define kDomainListDefaultDomainColumnIndex 0
99 #define kDomainListDefaultDomainColumnWidth 140
103 #define kServiceListDefaultServiceColumnIndex 0
104 #define kServiceListDefaultServiceColumnWidth 140
108 #define kChooserListDefaultNameColumnIndex 0
109 #define kChooserListDefaultNameColumnWidth 162
111 #define kChooserListDefaultIPColumnIndex 1
112 #define kChooserListDefaultIPColumnWidth 126
114 // Windows User Messages
116 #define WM_USER_DOMAIN_ADD ( WM_USER + 0x100 )
117 #define WM_USER_DOMAIN_REMOVE ( WM_USER + 0x101 )
118 #define WM_USER_SERVICE_ADD ( WM_USER + 0x102 )
119 #define WM_USER_SERVICE_REMOVE ( WM_USER + 0x103 )
120 #define WM_USER_RESOLVE ( WM_USER + 0x104 )
123 #pragma mark == Constants - Service Table ==
126 //===========================================================================================================================
127 // Constants - Service Table
128 //===========================================================================================================================
130 struct KnownServiceEntry
132 const char * serviceType
;
133 const char * description
;
134 const char * urlScheme
;
138 static const KnownServiceEntry kKnownServiceTable
[] =
140 { "_airport._tcp.", "AirPort Base Station", "acp://", false },
141 { "_afpovertcp._tcp.", "AppleShare Server", "afp://", false },
142 { "_ftp._tcp.", "File Transfer (FTP)", "ftp://", false },
143 { "_ichat._tcp.", "iChat", "ichat://", false },
144 { "_printer._tcp.", "Printer (LPD)", "ldp://", false },
145 { "_eppc._tcp.", "Remote AppleEvents", "eppc://", false },
146 { "_ssh._tcp.", "Secure Shell (SSH)", "ssh://", false },
147 { "_tftp._tcp.", "Trivial File Transfer (TFTP)", "tftp://", false },
148 { "_http._tcp.", "Web Server (HTTP)", "http://", true },
149 { "_smb._tcp.", "Windows File Sharing", "smb://", false },
150 { "_xserveraid._tcp.", "Xserve RAID", "xsr://", false },
151 { NULL
, NULL
, NULL
, false },
155 #pragma mark == Structures ==
158 //===========================================================================================================================
160 //===========================================================================================================================
162 struct DomainEventInfo
164 DNSBrowserEventType eventType
;
166 DNSNetworkAddress ifIP
;
169 struct ServiceEventInfo
171 DNSBrowserEventType eventType
;
175 DNSNetworkAddress ifIP
;
179 #pragma mark == Prototypes ==
182 //===========================================================================================================================
184 //===========================================================================================================================
190 DNSStatus inStatusCode
,
191 const DNSBrowserEvent
* inEvent
);
193 static char * DNSNetworkAddressToString( const DNSNetworkAddress
*inAddr
, char *outString
);
195 static DWORD
UTF8StringToStringObject( const char *inUTF8
, CString
&inObject
);
198 #pragma mark == Message Map ==
201 //===========================================================================================================================
203 //===========================================================================================================================
205 BEGIN_MESSAGE_MAP(ChooserDialog
, CDialog
)
206 //{{AFX_MSG_MAP(ChooserDialog)
208 ON_NOTIFY(LVN_ITEMCHANGED
, IDC_DOMAIN_LIST
, OnDomainListChanged
)
209 ON_NOTIFY(LVN_ITEMCHANGED
, IDC_SERVICE_LIST
, OnServiceListChanged
)
210 ON_NOTIFY(LVN_ITEMCHANGED
, IDC_CHOOSER_LIST
, OnChooserListChanged
)
211 ON_NOTIFY(NM_DBLCLK
, IDC_CHOOSER_LIST
, OnChooserListDoubleClick
)
212 ON_COMMAND(ID_HELP_ABOUT
, OnAbout
)
213 ON_WM_INITMENUPOPUP()
215 ON_COMMAND(ID_FILE_CLOSE
, OnFileClose
)
216 ON_COMMAND(ID_FILE_EXIT
, OnExit
)
220 ON_MESSAGE( WM_USER_DOMAIN_ADD
, OnDomainAdd
)
221 ON_MESSAGE( WM_USER_DOMAIN_REMOVE
, OnDomainRemove
)
222 ON_MESSAGE( WM_USER_SERVICE_ADD
, OnServiceAdd
)
223 ON_MESSAGE( WM_USER_SERVICE_REMOVE
, OnServiceRemove
)
224 ON_MESSAGE( WM_USER_RESOLVE
, OnResolve
)
228 #pragma mark == Routines ==
231 //===========================================================================================================================
233 //===========================================================================================================================
235 ChooserDialog::ChooserDialog( CWnd
*inParent
)
236 : CDialog( ChooserDialog::IDD
, inParent
)
238 //{{AFX_DATA_INIT(ChooserDialog)
239 // NOTE: the ClassWizard will add member initialization here
242 // Load menu accelerator table.
244 mMenuAcceleratorTable
= ::LoadAccelerators( AfxGetInstanceHandle(), MAKEINTRESOURCE( IDR_CHOOSER_DIALOG_MENU_ACCELERATORS
) );
245 assert( mMenuAcceleratorTable
);
248 mIsServiceBrowsing
= false;
251 //===========================================================================================================================
253 //===========================================================================================================================
255 ChooserDialog::~ChooserDialog( void )
261 err
= DNSBrowserRelease( mBrowser
, 0 );
262 assert( err
== kDNSNoErr
);
266 //===========================================================================================================================
268 //===========================================================================================================================
270 void ChooserDialog::DoDataExchange( CDataExchange
*pDX
)
272 CDialog::DoDataExchange(pDX
);
274 //{{AFX_DATA_MAP(ChooserDialog)
275 DDX_Control(pDX
, IDC_SERVICE_LIST
, mServiceList
);
276 DDX_Control(pDX
, IDC_DOMAIN_LIST
, mDomainList
);
277 DDX_Control(pDX
, IDC_CHOOSER_LIST
, mChooserList
);
281 //===========================================================================================================================
283 //===========================================================================================================================
285 BOOL
ChooserDialog::OnInitDialog( void )
291 // Initialize our parent.
293 CDialog::OnInitDialog();
295 // Set up the Domain List.
297 result
= tempString
.LoadString( IDS_CHOOSER_DOMAIN_COLUMN_NAME
);
299 mDomainList
.InsertColumn( 0, tempString
, LVCFMT_LEFT
, kDomainListDefaultDomainColumnWidth
);
301 // Set up the Service List.
303 result
= tempString
.LoadString( IDS_CHOOSER_SERVICE_COLUMN_NAME
);
305 mServiceList
.InsertColumn( 0, tempString
, LVCFMT_LEFT
, kServiceListDefaultServiceColumnWidth
);
307 PopulateServicesList();
309 // Set up the Chooser List.
311 result
= tempString
.LoadString( IDS_CHOOSER_CHOOSER_NAME_COLUMN_NAME
);
313 mChooserList
.InsertColumn( 0, tempString
, LVCFMT_LEFT
, kChooserListDefaultNameColumnWidth
);
315 result
= tempString
.LoadString( IDS_CHOOSER_CHOOSER_IP_COLUMN_NAME
);
317 mChooserList
.InsertColumn( 1, tempString
, LVCFMT_LEFT
, kChooserListDefaultIPColumnWidth
);
319 // Set up the other controls.
323 // Start browsing for domains.
325 err
= DNSBrowserCreate( 0, BrowserCallBack
, this, &mBrowser
);
326 assert( err
== kDNSNoErr
);
328 err
= DNSBrowserStartDomainSearch( mBrowser
, 0 );
329 assert( err
== kDNSNoErr
);
334 //===========================================================================================================================
336 //===========================================================================================================================
338 void ChooserDialog::OnFileClose()
343 //===========================================================================================================================
345 //===========================================================================================================================
347 void ChooserDialog::OnActivate( UINT nState
, CWnd
* pWndOther
, BOOL bMinimized
)
349 // Always make the active window the "main" window so modal dialogs work better and the app quits after closing
352 gApp
.m_pMainWnd
= this;
354 CDialog::OnActivate(nState
, pWndOther
, bMinimized
);
357 //===========================================================================================================================
359 //===========================================================================================================================
361 void ChooserDialog::PostNcDestroy()
363 // Call the base class to do the normal cleanup.
368 //===========================================================================================================================
369 // PreTranslateMessage
370 //===========================================================================================================================
372 BOOL
ChooserDialog::PreTranslateMessage(MSG
* pMsg
)
377 assert( mMenuAcceleratorTable
);
378 if( mMenuAcceleratorTable
)
380 result
= ::TranslateAccelerator( m_hWnd
, mMenuAcceleratorTable
, pMsg
);
384 result
= CDialog::PreTranslateMessage( pMsg
);
389 //===========================================================================================================================
391 //===========================================================================================================================
393 void ChooserDialog::OnInitMenuPopup( CMenu
*pPopupMenu
, UINT nIndex
, BOOL bSysMenu
)
395 CDialog::OnInitMenuPopup( pPopupMenu
, nIndex
, bSysMenu
);
399 case kChooserMenuIndexFile
:
402 case kChooserMenuIndexHelp
:
410 //===========================================================================================================================
412 //===========================================================================================================================
414 void ChooserDialog::OnExit()
416 AfxPostQuitMessage( 0 );
419 //===========================================================================================================================
421 //===========================================================================================================================
423 void ChooserDialog::OnAbout()
430 //===========================================================================================================================
432 //===========================================================================================================================
434 void ChooserDialog::OnSysCommand( UINT inID
, LPARAM inParam
)
436 CDialog::OnSysCommand( inID
, inParam
);
439 //===========================================================================================================================
441 //===========================================================================================================================
443 void ChooserDialog::OnClose()
447 gApp
.m_pMainWnd
= this;
451 //===========================================================================================================================
453 //===========================================================================================================================
455 void ChooserDialog::OnNcDestroy()
457 gApp
.m_pMainWnd
= this;
459 CDialog::OnNcDestroy();
462 //===========================================================================================================================
463 // OnDomainListChanged
464 //===========================================================================================================================
466 void ChooserDialog::OnDomainListChanged( NMHDR
*pNMHDR
, LRESULT
*pResult
)
468 UNUSED_ALWAYS( pNMHDR
);
470 // Domain list changes have similar effects to service list changes so reuse that code path by calling it here.
472 OnServiceListChanged( NULL
, NULL
);
477 //===========================================================================================================================
478 // OnServiceListChanged
479 //===========================================================================================================================
481 void ChooserDialog::OnServiceListChanged( NMHDR
*pNMHDR
, LRESULT
*pResult
)
486 UNUSED_ALWAYS( pNMHDR
);
488 // Stop any existing service search.
492 // If a domain and service type are selected, start searching for the service type on the domain.
494 selectedType
= mServiceList
.GetNextItem( -1, LVNI_SELECTED
);
495 selectedDomain
= mDomainList
.GetNextItem( -1, LVNI_SELECTED
);
497 if( ( selectedType
>= 0 ) && ( selectedDomain
>= 0 ) )
502 type
= mServiceTypes
[ selectedType
].serviceType
.c_str();
503 domain
= mDomainList
.GetItemText( selectedDomain
, 0 );
505 StartBrowsing( type
, domain
);
514 //===========================================================================================================================
515 // OnChooserListChanged
516 //===========================================================================================================================
518 void ChooserDialog::OnChooserListChanged( NMHDR
*pNMHDR
, LRESULT
*pResult
)
520 UNUSED_ALWAYS( pNMHDR
);
526 //===========================================================================================================================
527 // OnChooserListDoubleClick
528 //===========================================================================================================================
530 void ChooserDialog::OnChooserListDoubleClick( NMHDR
*pNMHDR
, LRESULT
*pResult
)
534 UNUSED_ALWAYS( pNMHDR
);
536 // Display the service instance if it is selected. Otherwise, clear all the info.
538 selectedItem
= mChooserList
.GetNextItem( -1, LVNI_SELECTED
);
539 if( selectedItem
>= 0 )
541 ServiceInstanceInfo
* p
;
543 const KnownServiceEntry
* service
;
545 assert( selectedItem
< (int) mServiceInstances
.size() );
546 p
= &mServiceInstances
[ selectedItem
];
548 // Search for a known service type entry that matches.
550 for( service
= kKnownServiceTable
; service
->serviceType
; ++service
)
552 if( p
->type
== service
->serviceType
)
557 if( service
->serviceType
)
559 // Create a URL representing the service instance. Special case for SMB (no port number).
561 if( strcmp( service
->serviceType
, "_smb._tcp" ) == 0 )
563 url
.Format( "%s%s/", service
->urlScheme
, (const char *) p
->ip
.c_str() );
569 text
= service
->useText
? p
->text
.c_str() : "";
570 url
.Format( "%s%s/%s", service
->urlScheme
, (const char *) p
->ip
.c_str(), text
);
573 // Let the system open the URL in the correct app.
575 ShellExecute( NULL
, "open", url
, "", "c:\\", SW_SHOWNORMAL
);
581 //===========================================================================================================================
583 //===========================================================================================================================
585 void ChooserDialog::OnCancel()
590 //===========================================================================================================================
591 // PopulateServicesList
592 //===========================================================================================================================
594 void ChooserDialog::PopulateServicesList( void )
596 ServiceTypeVector::iterator i
;
599 // Add a fixed list of known services.
601 if( mServiceTypes
.empty() )
603 const KnownServiceEntry
* service
;
605 for( service
= kKnownServiceTable
; service
->serviceType
; ++service
)
607 ServiceTypeInfo info
;
609 info
.serviceType
= service
->serviceType
;
610 info
.description
= service
->description
;
611 info
.urlScheme
= service
->urlScheme
;
612 mServiceTypes
.push_back( info
);
616 // Add each service to the list.
618 for( i
= mServiceTypes
.begin(); i
!= mServiceTypes
.end(); ++i
)
620 UTF8StringToStringObject( ( *i
).description
.c_str(), name
);
621 mServiceList
.InsertItem( mServiceList
.GetItemCount(), name
);
624 // Select the first service type by default.
626 if( !mServiceTypes
.empty() )
628 mServiceList
.SetItemState( 0, LVIS_SELECTED
| LVIS_FOCUSED
, LVIS_SELECTED
| LVIS_FOCUSED
);
632 //===========================================================================================================================
634 //===========================================================================================================================
636 void ChooserDialog::UpdateInfoDisplay( void )
646 // Display the service instance if it is selected. Otherwise, clear all the info.
648 selectedItem
= mChooserList
.GetNextItem( -1, LVNI_SELECTED
);
649 if( selectedItem
>= 0 )
651 ServiceInstanceInfo
* p
;
653 assert( selectedItem
< (int) mServiceInstances
.size() );
654 p
= &mServiceInstances
[ selectedItem
];
661 // Sync up the list items with the actual data (IP address may change).
663 mChooserList
.SetItemText( selectedItem
, 1, ip
.c_str() );
668 item
= (CWnd
*) this->GetDlgItem( IDC_INFO_NAME_TEXT
);
670 UTF8StringToStringObject( name
.c_str(), s
);
671 item
->SetWindowText( s
);
675 item
= (CWnd
*) this->GetDlgItem( IDC_INFO_IP_TEXT
);
677 item
->SetWindowText( ip
.c_str() );
681 item
= (CWnd
*) this->GetDlgItem( IDC_INFO_INTERFACE_TEXT
);
683 item
->SetWindowText( ifIP
.c_str() );
687 if( text
.size() > 255 )
691 item
= (CWnd
*) this->GetDlgItem( IDC_INFO_TEXT_TEXT
);
693 item
->SetWindowText( text
.c_str() );
700 //===========================================================================================================================
702 //===========================================================================================================================
704 LONG
ChooserDialog::OnDomainAdd( WPARAM inWParam
, LPARAM inLParam
)
707 std::auto_ptr
< DomainEventInfo
> pAutoPtr
;
714 UNUSED_ALWAYS( inWParam
);
717 p
= reinterpret_cast <DomainEventInfo
*> ( inLParam
);
720 // Search to see if we already know about this domain. If not, add it to the list.
724 n
= mDomainList
.GetItemCount();
725 for( i
= 0; i
< n
; ++i
)
727 s
= mDomainList
.GetItemText( i
, 0 );
738 mDomainList
.InsertItem( n
, domain
);
740 // If no domains are selected and the domain being added is a default domain, select it.
742 selectedItem
= mDomainList
.GetNextItem( -1, LVNI_SELECTED
);
743 if( ( selectedItem
< 0 ) && ( p
->eventType
== kDNSBrowserEventTypeAddDefaultDomain
) )
745 mDomainList
.SetItemState( n
, LVIS_SELECTED
| LVIS_FOCUSED
, LVIS_SELECTED
| LVIS_FOCUSED
);
751 //===========================================================================================================================
753 //===========================================================================================================================
755 LONG
ChooserDialog::OnDomainRemove( WPARAM inWParam
, LPARAM inLParam
)
758 std::auto_ptr
< DomainEventInfo
> pAutoPtr
;
765 UNUSED_ALWAYS( inWParam
);
768 p
= reinterpret_cast <DomainEventInfo
*> ( inLParam
);
771 // Search to see if we know about this domain. If so, remove it from the list.
775 n
= mDomainList
.GetItemCount();
776 for( i
= 0; i
< n
; ++i
)
778 s
= mDomainList
.GetItemText( i
, 0 );
787 mDomainList
.DeleteItem( i
);
792 //===========================================================================================================================
794 //===========================================================================================================================
796 LONG
ChooserDialog::OnServiceAdd( WPARAM inWParam
, LPARAM inLParam
)
798 ServiceEventInfo
* p
;
799 std::auto_ptr
< ServiceEventInfo
> pAutoPtr
;
801 UNUSED_ALWAYS( inWParam
);
804 p
= reinterpret_cast <ServiceEventInfo
*> ( inLParam
);
810 //===========================================================================================================================
812 //===========================================================================================================================
814 LONG
ChooserDialog::OnServiceRemove( WPARAM inWParam
, LPARAM inLParam
)
816 ServiceEventInfo
* p
;
817 std::auto_ptr
< ServiceEventInfo
> pAutoPtr
;
822 UNUSED_ALWAYS( inWParam
);
825 p
= reinterpret_cast <ServiceEventInfo
*> ( inLParam
);
828 // Search to see if we know about this service instance. If so, remove it from the list.
831 n
= (int) mServiceInstances
.size();
832 for( i
= 0; i
< n
; ++i
)
834 ServiceInstanceInfo
* q
;
836 // If the name, type, domain, and interface match, treat it as the same service instance.
838 q
= &mServiceInstances
[ i
];
839 if( ( p
->name
== q
->name
) &&
840 ( p
->type
== q
->type
) &&
841 ( p
->domain
== q
->domain
) )
849 mChooserList
.DeleteItem( i
);
850 assert( i
< (int) mServiceInstances
.size() );
851 mServiceInstances
.erase( mServiceInstances
.begin() + i
);
856 //===========================================================================================================================
858 //===========================================================================================================================
860 LONG
ChooserDialog::OnResolve( WPARAM inWParam
, LPARAM inLParam
)
862 ServiceInstanceInfo
* p
;
863 std::auto_ptr
< ServiceInstanceInfo
> pAutoPtr
;
869 UNUSED_ALWAYS( inWParam
);
872 p
= reinterpret_cast <ServiceInstanceInfo
*> ( inLParam
);
875 // Make sure it is for an item of the correct type. This handles any resolves that may have been queued up.
877 selectedType
= mServiceList
.GetNextItem( -1, LVNI_SELECTED
);
878 assert( selectedType
>= 0 );
879 if( selectedType
>= 0 )
881 assert( selectedType
<= (int) mServiceTypes
.size() );
882 if( p
->type
!= mServiceTypes
[ selectedType
].serviceType
)
888 // Search to see if we know about this service instance. If so, update its info. Otherwise, add it to the list.
891 n
= (int) mServiceInstances
.size();
892 for( i
= 0; i
< n
; ++i
)
894 ServiceInstanceInfo
* q
;
896 // If the name, type, domain, and interface matches, treat it as the same service instance.
898 q
= &mServiceInstances
[ i
];
899 if( ( p
->name
== q
->name
) &&
900 ( p
->type
== q
->type
) &&
901 ( p
->domain
== q
->domain
) &&
902 ( p
->ifIP
== q
->ifIP
) )
910 mServiceInstances
[ i
] = *p
;
916 mServiceInstances
.push_back( *p
);
917 UTF8StringToStringObject( p
->name
.c_str(), s
);
918 mChooserList
.InsertItem( n
, s
);
919 mChooserList
.SetItemText( n
, 1, p
->ip
.c_str() );
921 // If this is the only item, select it.
925 mChooserList
.SetItemState( n
, LVIS_SELECTED
| LVIS_FOCUSED
, LVIS_SELECTED
| LVIS_FOCUSED
);
934 //===========================================================================================================================
936 //===========================================================================================================================
938 void ChooserDialog::StartBrowsing( const char *inType
, const char *inDomain
)
942 assert( mServiceInstances
.empty() );
943 assert( mChooserList
.GetItemCount() == 0 );
944 assert( !mIsServiceBrowsing
);
946 mChooserList
.DeleteAllItems();
947 mServiceInstances
.clear();
949 mIsServiceBrowsing
= true;
950 err
= DNSBrowserStartServiceSearch( mBrowser
, kDNSBrowserFlagAutoResolve
, inType
, inDomain
);
951 assert( err
== kDNSNoErr
);
954 //===========================================================================================================================
956 //===========================================================================================================================
958 void ChooserDialog::StopBrowsing( void )
960 // If searching, stop.
962 if( mIsServiceBrowsing
)
966 mIsServiceBrowsing
= false;
967 err
= DNSBrowserStopServiceSearch( mBrowser
, 0 );
968 assert( err
== kDNSNoErr
);
971 // Remove all service instances.
973 mChooserList
.DeleteAllItems();
974 assert( mChooserList
.GetItemCount() == 0 );
975 mServiceInstances
.clear();
976 assert( mServiceInstances
.empty() );
984 //===========================================================================================================================
986 //===========================================================================================================================
992 DNSStatus inStatusCode
,
993 const DNSBrowserEvent
* inEvent
)
995 ChooserDialog
* dialog
;
999 UNUSED_ALWAYS( inStatusCode
);
1000 UNUSED_ALWAYS( inRef
);
1002 // Check parameters.
1004 assert( inContext
);
1005 dialog
= reinterpret_cast <ChooserDialog
*> ( inContext
);
1009 switch( inEvent
->type
)
1011 case kDNSBrowserEventTypeRelease
:
1016 case kDNSBrowserEventTypeAddDomain
:
1017 case kDNSBrowserEventTypeAddDefaultDomain
:
1018 case kDNSBrowserEventTypeRemoveDomain
:
1020 DomainEventInfo
* domain
;
1021 std::auto_ptr
< DomainEventInfo
> domainAutoPtr
;
1023 domain
= new DomainEventInfo
;
1024 domainAutoPtr
.reset( domain
);
1026 domain
->eventType
= inEvent
->type
;
1027 domain
->domain
= inEvent
->data
.addDomain
.domain
;
1028 domain
->ifIP
= inEvent
->data
.addDomain
.interfaceIP
;
1030 message
= ( inEvent
->type
== kDNSBrowserEventTypeRemoveDomain
) ? WM_USER_DOMAIN_REMOVE
: WM_USER_DOMAIN_ADD
;
1031 posted
= ::PostMessage( dialog
->GetSafeHwnd(), message
, 0, (LPARAM
) domain
);
1035 domainAutoPtr
.release();
1042 case kDNSBrowserEventTypeAddService
:
1043 case kDNSBrowserEventTypeRemoveService
:
1045 ServiceEventInfo
* service
;
1046 std::auto_ptr
< ServiceEventInfo
> serviceAutoPtr
;
1048 service
= new ServiceEventInfo
;
1049 serviceAutoPtr
.reset( service
);
1051 service
->eventType
= inEvent
->type
;
1052 service
->name
= inEvent
->data
.addService
.name
;
1053 service
->type
= inEvent
->data
.addService
.type
;
1054 service
->domain
= inEvent
->data
.addService
.domain
;
1055 service
->ifIP
= inEvent
->data
.addService
.interfaceIP
;
1057 message
= ( inEvent
->type
== kDNSBrowserEventTypeAddService
) ? WM_USER_SERVICE_ADD
: WM_USER_SERVICE_REMOVE
;
1058 posted
= ::PostMessage( dialog
->GetSafeHwnd(), message
, 0, (LPARAM
) service
);
1062 serviceAutoPtr
.release();
1069 case kDNSBrowserEventTypeResolved
:
1071 ServiceInstanceInfo
* serviceInstance
;
1072 std::auto_ptr
< ServiceInstanceInfo
> serviceInstanceAutoPtr
;
1075 serviceInstance
= new ServiceInstanceInfo
;
1076 serviceInstanceAutoPtr
.reset( serviceInstance
);
1078 serviceInstance
->name
= inEvent
->data
.resolved
->name
;
1079 serviceInstance
->type
= inEvent
->data
.resolved
->type
;
1080 serviceInstance
->domain
= inEvent
->data
.resolved
->domain
;
1081 serviceInstance
->ip
= DNSNetworkAddressToString( &inEvent
->data
.resolved
->address
, s
);
1082 serviceInstance
->ifIP
= DNSNetworkAddressToString( &inEvent
->data
.resolved
->interfaceIP
, s
);
1083 serviceInstance
->text
= inEvent
->data
.resolved
->textRecord
;
1085 posted
= ::PostMessage( dialog
->GetSafeHwnd(), WM_USER_RESOLVE
, 0, (LPARAM
) serviceInstance
);
1089 serviceInstanceAutoPtr
.release();
1100 // Don't let exceptions escape.
1104 //===========================================================================================================================
1105 // DNSNetworkAddressToString
1107 // Note: Currently only supports IPv4 network addresses.
1108 //===========================================================================================================================
1110 static char * DNSNetworkAddressToString( const DNSNetworkAddress
*inAddr
, char *outString
)
1115 p
= inAddr
->u
.ipv4
.addr
.v8
;
1116 port
= ntohs( inAddr
->u
.ipv4
.port
.v16
);
1117 if( port
!= kDNSPortInvalid
)
1119 sprintf( outString
, "%u.%u.%u.%u:%u", p
[ 0 ], p
[ 1 ], p
[ 2 ], p
[ 3 ], port
);
1123 sprintf( outString
, "%u.%u.%u.%u", p
[ 0 ], p
[ 1 ], p
[ 2 ], p
[ 3 ] );
1125 return( outString
);
1128 //===========================================================================================================================
1129 // UTF8StringToStringObject
1130 //===========================================================================================================================
1132 static DWORD
UTF8StringToStringObject( const char *inUTF8
, CString
&inObject
)
1140 n
= MultiByteToWideChar( CP_UTF8
, 0, inUTF8
, -1, NULL
, 0 );
1143 unicode
= (BSTR
) malloc( (size_t)( n
* sizeof( wchar_t ) ) );
1146 err
= ERROR_INSUFFICIENT_BUFFER
;
1150 n
= MultiByteToWideChar( CP_UTF8
, 0, inUTF8
, -1, unicode
, n
);
1157 err
= ERROR_NO_UNICODE_TRANSLATION
;