2 * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
23 Change History (most recent first):
25 $Log: ChooserDialog.cpp,v $
26 Revision 1.1 2003/08/21 02:06:47 bradley
27 Moved Rendezvous Browser for non-Windows CE into Windows sub-folder.
29 Revision 1.7 2003/08/20 06:45:56 bradley
30 Updated for IP address changes in DNSServices. Added support for browsing for Xserve RAID.
32 Revision 1.6 2003/08/12 19:56:28 cheshire
35 Revision 1.5 2003/07/13 01:03:55 cheshire
36 Diffs provided by Bob Bradley to provide provide proper display of Unicode names
38 Revision 1.4 2003/07/02 21:20:06 cheshire
39 <rdar://problem/3313413> Update copyright notices, etc., in source code comments
41 Revision 1.3 2002/09/21 20:44:55 zarzycki
44 Revision 1.2 2002/09/20 08:39:21 bradley
45 Make sure each resolved item matches the selected service type to handle resolved that may have
46 been queued up on the Windows Message Loop. Reduce column to fit when scrollbar is present.
48 Revision 1.1 2002/09/20 06:12:52 bradley
49 Rendezvous Browser for Windows
64 #include "DNSServices.h"
66 #include "Application.h"
67 #include "AboutDialog.h"
70 #include "ChooserDialog.h"
75 static char THIS_FILE
[] = __FILE__
;
79 #pragma mark == Constants ==
82 //===========================================================================================================================
84 //===========================================================================================================================
90 kChooserMenuIndexFile
= 0,
91 kChooserMenuIndexHelp
= 1
96 #define kDomainListDefaultDomainColumnIndex 0
97 #define kDomainListDefaultDomainColumnWidth 140
101 #define kServiceListDefaultServiceColumnIndex 0
102 #define kServiceListDefaultServiceColumnWidth 140
106 #define kChooserListDefaultNameColumnIndex 0
107 #define kChooserListDefaultNameColumnWidth 162
109 #define kChooserListDefaultIPColumnIndex 1
110 #define kChooserListDefaultIPColumnWidth 126
112 // Windows User Messages
114 #define WM_USER_DOMAIN_ADD ( WM_USER + 0x100 )
115 #define WM_USER_DOMAIN_REMOVE ( WM_USER + 0x101 )
116 #define WM_USER_SERVICE_ADD ( WM_USER + 0x102 )
117 #define WM_USER_SERVICE_REMOVE ( WM_USER + 0x103 )
118 #define WM_USER_RESOLVE ( WM_USER + 0x104 )
121 #pragma mark == Constants - Service Table ==
124 //===========================================================================================================================
125 // Constants - Service Table
126 //===========================================================================================================================
128 struct KnownServiceEntry
130 const char * serviceType
;
131 const char * description
;
132 const char * urlScheme
;
136 static const KnownServiceEntry kKnownServiceTable
[] =
138 { "_airport._tcp.", "AirPort Base Station", "acp://", false },
139 { "_afpovertcp._tcp.", "AppleShare Server", "afp://", false },
140 { "_ftp._tcp.", "File Transfer (FTP)", "ftp://", false },
141 { "_ichat._tcp.", "iChat", "ichat://", false },
142 { "_printer._tcp.", "Printer (LPD)", "ldp://", false },
143 { "_eppc._tcp.", "Remote AppleEvents", "eppc://", false },
144 { "_ssh._tcp.", "Secure Shell (SSH)", "ssh://", false },
145 { "_tftp._tcp.", "Trivial File Transfer (TFTP)", "tftp://", false },
146 { "_http._tcp.", "Web Server (HTTP)", "http://", true },
147 { "_smb._tcp.", "Windows File Sharing", "smb://", false },
148 { "_xserveraid._tcp.", "Xserve RAID", "xsr://", false },
149 { NULL
, NULL
, NULL
, false },
153 #pragma mark == Structures ==
156 //===========================================================================================================================
158 //===========================================================================================================================
160 struct DomainEventInfo
162 DNSBrowserEventType eventType
;
164 DNSNetworkAddress ifIP
;
167 struct ServiceEventInfo
169 DNSBrowserEventType eventType
;
173 DNSNetworkAddress ifIP
;
177 #pragma mark == Prototypes ==
180 //===========================================================================================================================
182 //===========================================================================================================================
188 DNSStatus inStatusCode
,
189 const DNSBrowserEvent
* inEvent
);
191 static char * DNSNetworkAddressToString( const DNSNetworkAddress
*inAddr
, char *outString
);
193 static DWORD
UTF8StringToStringObject( const char *inUTF8
, CString
&inObject
);
196 #pragma mark == Message Map ==
199 //===========================================================================================================================
201 //===========================================================================================================================
203 BEGIN_MESSAGE_MAP(ChooserDialog
, CDialog
)
204 //{{AFX_MSG_MAP(ChooserDialog)
206 ON_NOTIFY(LVN_ITEMCHANGED
, IDC_DOMAIN_LIST
, OnDomainListChanged
)
207 ON_NOTIFY(LVN_ITEMCHANGED
, IDC_SERVICE_LIST
, OnServiceListChanged
)
208 ON_NOTIFY(LVN_ITEMCHANGED
, IDC_CHOOSER_LIST
, OnChooserListChanged
)
209 ON_NOTIFY(NM_DBLCLK
, IDC_CHOOSER_LIST
, OnChooserListDoubleClick
)
210 ON_COMMAND(ID_HELP_ABOUT
, OnAbout
)
211 ON_WM_INITMENUPOPUP()
213 ON_COMMAND(ID_FILE_CLOSE
, OnFileClose
)
214 ON_COMMAND(ID_FILE_EXIT
, OnExit
)
218 ON_MESSAGE( WM_USER_DOMAIN_ADD
, OnDomainAdd
)
219 ON_MESSAGE( WM_USER_DOMAIN_REMOVE
, OnDomainRemove
)
220 ON_MESSAGE( WM_USER_SERVICE_ADD
, OnServiceAdd
)
221 ON_MESSAGE( WM_USER_SERVICE_REMOVE
, OnServiceRemove
)
222 ON_MESSAGE( WM_USER_RESOLVE
, OnResolve
)
226 #pragma mark == Routines ==
229 //===========================================================================================================================
231 //===========================================================================================================================
233 ChooserDialog::ChooserDialog( CWnd
*inParent
)
234 : CDialog( ChooserDialog::IDD
, inParent
)
236 //{{AFX_DATA_INIT(ChooserDialog)
237 // NOTE: the ClassWizard will add member initialization here
240 // Load menu accelerator table.
242 mMenuAcceleratorTable
= ::LoadAccelerators( AfxGetInstanceHandle(), MAKEINTRESOURCE( IDR_CHOOSER_DIALOG_MENU_ACCELERATORS
) );
243 assert( mMenuAcceleratorTable
);
246 mIsServiceBrowsing
= false;
249 //===========================================================================================================================
251 //===========================================================================================================================
253 ChooserDialog::~ChooserDialog( void )
259 err
= DNSBrowserRelease( mBrowser
, 0 );
260 assert( err
== kDNSNoErr
);
264 //===========================================================================================================================
266 //===========================================================================================================================
268 void ChooserDialog::DoDataExchange( CDataExchange
*pDX
)
270 CDialog::DoDataExchange(pDX
);
272 //{{AFX_DATA_MAP(ChooserDialog)
273 DDX_Control(pDX
, IDC_SERVICE_LIST
, mServiceList
);
274 DDX_Control(pDX
, IDC_DOMAIN_LIST
, mDomainList
);
275 DDX_Control(pDX
, IDC_CHOOSER_LIST
, mChooserList
);
279 //===========================================================================================================================
281 //===========================================================================================================================
283 BOOL
ChooserDialog::OnInitDialog( void )
289 // Initialize our parent.
291 CDialog::OnInitDialog();
293 // Set up the Domain List.
295 result
= tempString
.LoadString( IDS_CHOOSER_DOMAIN_COLUMN_NAME
);
297 mDomainList
.InsertColumn( 0, tempString
, LVCFMT_LEFT
, kDomainListDefaultDomainColumnWidth
);
299 // Set up the Service List.
301 result
= tempString
.LoadString( IDS_CHOOSER_SERVICE_COLUMN_NAME
);
303 mServiceList
.InsertColumn( 0, tempString
, LVCFMT_LEFT
, kServiceListDefaultServiceColumnWidth
);
305 PopulateServicesList();
307 // Set up the Chooser List.
309 result
= tempString
.LoadString( IDS_CHOOSER_CHOOSER_NAME_COLUMN_NAME
);
311 mChooserList
.InsertColumn( 0, tempString
, LVCFMT_LEFT
, kChooserListDefaultNameColumnWidth
);
313 result
= tempString
.LoadString( IDS_CHOOSER_CHOOSER_IP_COLUMN_NAME
);
315 mChooserList
.InsertColumn( 1, tempString
, LVCFMT_LEFT
, kChooserListDefaultIPColumnWidth
);
317 // Set up the other controls.
321 // Start browsing for domains.
323 err
= DNSBrowserCreate( 0, BrowserCallBack
, this, &mBrowser
);
324 assert( err
== kDNSNoErr
);
326 err
= DNSBrowserStartDomainSearch( mBrowser
, 0 );
327 assert( err
== kDNSNoErr
);
332 //===========================================================================================================================
334 //===========================================================================================================================
336 void ChooserDialog::OnFileClose()
341 //===========================================================================================================================
343 //===========================================================================================================================
345 void ChooserDialog::OnActivate( UINT nState
, CWnd
* pWndOther
, BOOL bMinimized
)
347 // Always make the active window the "main" window so modal dialogs work better and the app quits after closing
350 gApp
.m_pMainWnd
= this;
352 CDialog::OnActivate(nState
, pWndOther
, bMinimized
);
355 //===========================================================================================================================
357 //===========================================================================================================================
359 void ChooserDialog::PostNcDestroy()
361 // Call the base class to do the normal cleanup.
366 //===========================================================================================================================
367 // PreTranslateMessage
368 //===========================================================================================================================
370 BOOL
ChooserDialog::PreTranslateMessage(MSG
* pMsg
)
375 assert( mMenuAcceleratorTable
);
376 if( mMenuAcceleratorTable
)
378 result
= ::TranslateAccelerator( m_hWnd
, mMenuAcceleratorTable
, pMsg
);
382 result
= CDialog::PreTranslateMessage( pMsg
);
387 //===========================================================================================================================
389 //===========================================================================================================================
391 void ChooserDialog::OnInitMenuPopup( CMenu
*pPopupMenu
, UINT nIndex
, BOOL bSysMenu
)
393 CDialog::OnInitMenuPopup( pPopupMenu
, nIndex
, bSysMenu
);
397 case kChooserMenuIndexFile
:
400 case kChooserMenuIndexHelp
:
408 //===========================================================================================================================
410 //===========================================================================================================================
412 void ChooserDialog::OnExit()
414 AfxPostQuitMessage( 0 );
417 //===========================================================================================================================
419 //===========================================================================================================================
421 void ChooserDialog::OnAbout()
428 //===========================================================================================================================
430 //===========================================================================================================================
432 void ChooserDialog::OnSysCommand( UINT inID
, LPARAM inParam
)
434 CDialog::OnSysCommand( inID
, inParam
);
437 //===========================================================================================================================
439 //===========================================================================================================================
441 void ChooserDialog::OnClose()
445 gApp
.m_pMainWnd
= this;
449 //===========================================================================================================================
451 //===========================================================================================================================
453 void ChooserDialog::OnNcDestroy()
455 gApp
.m_pMainWnd
= this;
457 CDialog::OnNcDestroy();
460 //===========================================================================================================================
461 // OnDomainListChanged
462 //===========================================================================================================================
464 void ChooserDialog::OnDomainListChanged( NMHDR
*pNMHDR
, LRESULT
*pResult
)
466 UNUSED_ALWAYS( pNMHDR
);
468 // Domain list changes have similar effects to service list changes so reuse that code path by calling it here.
470 OnServiceListChanged( NULL
, NULL
);
475 //===========================================================================================================================
476 // OnServiceListChanged
477 //===========================================================================================================================
479 void ChooserDialog::OnServiceListChanged( NMHDR
*pNMHDR
, LRESULT
*pResult
)
484 UNUSED_ALWAYS( pNMHDR
);
486 // Stop any existing service search.
490 // If a domain and service type are selected, start searching for the service type on the domain.
492 selectedType
= mServiceList
.GetNextItem( -1, LVNI_SELECTED
);
493 selectedDomain
= mDomainList
.GetNextItem( -1, LVNI_SELECTED
);
495 if( ( selectedType
>= 0 ) && ( selectedDomain
>= 0 ) )
500 type
= mServiceTypes
[ selectedType
].serviceType
.c_str();
501 domain
= mDomainList
.GetItemText( selectedDomain
, 0 );
503 StartBrowsing( type
, domain
);
512 //===========================================================================================================================
513 // OnChooserListChanged
514 //===========================================================================================================================
516 void ChooserDialog::OnChooserListChanged( NMHDR
*pNMHDR
, LRESULT
*pResult
)
518 UNUSED_ALWAYS( pNMHDR
);
524 //===========================================================================================================================
525 // OnChooserListDoubleClick
526 //===========================================================================================================================
528 void ChooserDialog::OnChooserListDoubleClick( NMHDR
*pNMHDR
, LRESULT
*pResult
)
532 UNUSED_ALWAYS( pNMHDR
);
534 // Display the service instance if it is selected. Otherwise, clear all the info.
536 selectedItem
= mChooserList
.GetNextItem( -1, LVNI_SELECTED
);
537 if( selectedItem
>= 0 )
539 ServiceInstanceInfo
* p
;
541 const KnownServiceEntry
* service
;
543 assert( selectedItem
< (int) mServiceInstances
.size() );
544 p
= &mServiceInstances
[ selectedItem
];
546 // Search for a known service type entry that matches.
548 for( service
= kKnownServiceTable
; service
->serviceType
; ++service
)
550 if( p
->type
== service
->serviceType
)
555 if( service
->serviceType
)
557 // Create a URL representing the service instance. Special case for SMB (no port number).
559 if( strcmp( service
->serviceType
, "_smb._tcp" ) == 0 )
561 url
.Format( "%s%s/", service
->urlScheme
, (const char *) p
->ip
.c_str() );
567 text
= service
->useText
? p
->text
.c_str() : "";
568 url
.Format( "%s%s/%s", service
->urlScheme
, (const char *) p
->ip
.c_str(), text
);
571 // Let the system open the URL in the correct app.
573 ShellExecute( NULL
, "open", url
, "", "c:\\", SW_SHOWNORMAL
);
579 //===========================================================================================================================
581 //===========================================================================================================================
583 void ChooserDialog::OnCancel()
588 //===========================================================================================================================
589 // PopulateServicesList
590 //===========================================================================================================================
592 void ChooserDialog::PopulateServicesList( void )
594 ServiceTypeVector::iterator i
;
597 // Add a fixed list of known services.
599 if( mServiceTypes
.empty() )
601 const KnownServiceEntry
* service
;
603 for( service
= kKnownServiceTable
; service
->serviceType
; ++service
)
605 ServiceTypeInfo info
;
607 info
.serviceType
= service
->serviceType
;
608 info
.description
= service
->description
;
609 info
.urlScheme
= service
->urlScheme
;
610 mServiceTypes
.push_back( info
);
614 // Add each service to the list.
616 for( i
= mServiceTypes
.begin(); i
!= mServiceTypes
.end(); ++i
)
618 UTF8StringToStringObject( ( *i
).description
.c_str(), name
);
619 mServiceList
.InsertItem( mServiceList
.GetItemCount(), name
);
622 // Select the first service type by default.
624 if( !mServiceTypes
.empty() )
626 mServiceList
.SetItemState( 0, LVIS_SELECTED
| LVIS_FOCUSED
, LVIS_SELECTED
| LVIS_FOCUSED
);
630 //===========================================================================================================================
632 //===========================================================================================================================
634 void ChooserDialog::UpdateInfoDisplay( void )
644 // Display the service instance if it is selected. Otherwise, clear all the info.
646 selectedItem
= mChooserList
.GetNextItem( -1, LVNI_SELECTED
);
647 if( selectedItem
>= 0 )
649 ServiceInstanceInfo
* p
;
651 assert( selectedItem
< (int) mServiceInstances
.size() );
652 p
= &mServiceInstances
[ selectedItem
];
659 // Sync up the list items with the actual data (IP address may change).
661 mChooserList
.SetItemText( selectedItem
, 1, ip
.c_str() );
666 item
= (CWnd
*) this->GetDlgItem( IDC_INFO_NAME_TEXT
);
668 UTF8StringToStringObject( name
.c_str(), s
);
669 item
->SetWindowText( s
);
673 item
= (CWnd
*) this->GetDlgItem( IDC_INFO_IP_TEXT
);
675 item
->SetWindowText( ip
.c_str() );
679 item
= (CWnd
*) this->GetDlgItem( IDC_INFO_INTERFACE_TEXT
);
681 item
->SetWindowText( ifIP
.c_str() );
685 if( text
.size() > 255 )
689 item
= (CWnd
*) this->GetDlgItem( IDC_INFO_TEXT_TEXT
);
691 item
->SetWindowText( text
.c_str() );
698 //===========================================================================================================================
700 //===========================================================================================================================
702 LONG
ChooserDialog::OnDomainAdd( WPARAM inWParam
, LPARAM inLParam
)
705 std::auto_ptr
< DomainEventInfo
> pAutoPtr
;
712 UNUSED_ALWAYS( inWParam
);
715 p
= reinterpret_cast <DomainEventInfo
*> ( inLParam
);
718 // Search to see if we already know about this domain. If not, add it to the list.
722 n
= mDomainList
.GetItemCount();
723 for( i
= 0; i
< n
; ++i
)
725 s
= mDomainList
.GetItemText( i
, 0 );
736 mDomainList
.InsertItem( n
, domain
);
738 // If no domains are selected and the domain being added is a default domain, select it.
740 selectedItem
= mDomainList
.GetNextItem( -1, LVNI_SELECTED
);
741 if( ( selectedItem
< 0 ) && ( p
->eventType
== kDNSBrowserEventTypeAddDefaultDomain
) )
743 mDomainList
.SetItemState( n
, LVIS_SELECTED
| LVIS_FOCUSED
, LVIS_SELECTED
| LVIS_FOCUSED
);
749 //===========================================================================================================================
751 //===========================================================================================================================
753 LONG
ChooserDialog::OnDomainRemove( WPARAM inWParam
, LPARAM inLParam
)
756 std::auto_ptr
< DomainEventInfo
> pAutoPtr
;
763 UNUSED_ALWAYS( inWParam
);
766 p
= reinterpret_cast <DomainEventInfo
*> ( inLParam
);
769 // Search to see if we know about this domain. If so, remove it from the list.
773 n
= mDomainList
.GetItemCount();
774 for( i
= 0; i
< n
; ++i
)
776 s
= mDomainList
.GetItemText( i
, 0 );
785 mDomainList
.DeleteItem( i
);
790 //===========================================================================================================================
792 //===========================================================================================================================
794 LONG
ChooserDialog::OnServiceAdd( WPARAM inWParam
, LPARAM inLParam
)
796 ServiceEventInfo
* p
;
797 std::auto_ptr
< ServiceEventInfo
> pAutoPtr
;
799 UNUSED_ALWAYS( inWParam
);
802 p
= reinterpret_cast <ServiceEventInfo
*> ( inLParam
);
808 //===========================================================================================================================
810 //===========================================================================================================================
812 LONG
ChooserDialog::OnServiceRemove( WPARAM inWParam
, LPARAM inLParam
)
814 ServiceEventInfo
* p
;
815 std::auto_ptr
< ServiceEventInfo
> pAutoPtr
;
820 UNUSED_ALWAYS( inWParam
);
823 p
= reinterpret_cast <ServiceEventInfo
*> ( inLParam
);
826 // Search to see if we know about this service instance. If so, remove it from the list.
829 n
= (int) mServiceInstances
.size();
830 for( i
= 0; i
< n
; ++i
)
832 ServiceInstanceInfo
* q
;
834 // If the name, type, domain, and interface match, treat it as the same service instance.
836 q
= &mServiceInstances
[ i
];
837 if( ( p
->name
== q
->name
) &&
838 ( p
->type
== q
->type
) &&
839 ( p
->domain
== q
->domain
) )
847 mChooserList
.DeleteItem( i
);
848 assert( i
< (int) mServiceInstances
.size() );
849 mServiceInstances
.erase( mServiceInstances
.begin() + i
);
854 //===========================================================================================================================
856 //===========================================================================================================================
858 LONG
ChooserDialog::OnResolve( WPARAM inWParam
, LPARAM inLParam
)
860 ServiceInstanceInfo
* p
;
861 std::auto_ptr
< ServiceInstanceInfo
> pAutoPtr
;
867 UNUSED_ALWAYS( inWParam
);
870 p
= reinterpret_cast <ServiceInstanceInfo
*> ( inLParam
);
873 // Make sure it is for an item of the correct type. This handles any resolves that may have been queued up.
875 selectedType
= mServiceList
.GetNextItem( -1, LVNI_SELECTED
);
876 assert( selectedType
>= 0 );
877 if( selectedType
>= 0 )
879 assert( selectedType
<= (int) mServiceTypes
.size() );
880 if( p
->type
!= mServiceTypes
[ selectedType
].serviceType
)
886 // Search to see if we know about this service instance. If so, update its info. Otherwise, add it to the list.
889 n
= (int) mServiceInstances
.size();
890 for( i
= 0; i
< n
; ++i
)
892 ServiceInstanceInfo
* q
;
894 // If the name, type, domain, and interface matches, treat it as the same service instance.
896 q
= &mServiceInstances
[ i
];
897 if( ( p
->name
== q
->name
) &&
898 ( p
->type
== q
->type
) &&
899 ( p
->domain
== q
->domain
) &&
900 ( p
->ifIP
== q
->ifIP
) )
908 mServiceInstances
[ i
] = *p
;
914 mServiceInstances
.push_back( *p
);
915 UTF8StringToStringObject( p
->name
.c_str(), s
);
916 mChooserList
.InsertItem( n
, s
);
917 mChooserList
.SetItemText( n
, 1, p
->ip
.c_str() );
919 // If this is the only item, select it.
923 mChooserList
.SetItemState( n
, LVIS_SELECTED
| LVIS_FOCUSED
, LVIS_SELECTED
| LVIS_FOCUSED
);
932 //===========================================================================================================================
934 //===========================================================================================================================
936 void ChooserDialog::StartBrowsing( const char *inType
, const char *inDomain
)
940 assert( mServiceInstances
.empty() );
941 assert( mChooserList
.GetItemCount() == 0 );
942 assert( !mIsServiceBrowsing
);
944 mChooserList
.DeleteAllItems();
945 mServiceInstances
.clear();
947 mIsServiceBrowsing
= true;
948 err
= DNSBrowserStartServiceSearch( mBrowser
, kDNSBrowserFlagAutoResolve
, inType
, inDomain
);
949 assert( err
== kDNSNoErr
);
952 //===========================================================================================================================
954 //===========================================================================================================================
956 void ChooserDialog::StopBrowsing( void )
958 // If searching, stop.
960 if( mIsServiceBrowsing
)
964 mIsServiceBrowsing
= false;
965 err
= DNSBrowserStopServiceSearch( mBrowser
, 0 );
966 assert( err
== kDNSNoErr
);
969 // Remove all service instances.
971 mChooserList
.DeleteAllItems();
972 assert( mChooserList
.GetItemCount() == 0 );
973 mServiceInstances
.clear();
974 assert( mServiceInstances
.empty() );
982 //===========================================================================================================================
984 //===========================================================================================================================
990 DNSStatus inStatusCode
,
991 const DNSBrowserEvent
* inEvent
)
993 ChooserDialog
* dialog
;
997 UNUSED_ALWAYS( inStatusCode
);
998 UNUSED_ALWAYS( inRef
);
1000 // Check parameters.
1002 assert( inContext
);
1003 dialog
= reinterpret_cast <ChooserDialog
*> ( inContext
);
1007 switch( inEvent
->type
)
1009 case kDNSBrowserEventTypeRelease
:
1014 case kDNSBrowserEventTypeAddDomain
:
1015 case kDNSBrowserEventTypeAddDefaultDomain
:
1016 case kDNSBrowserEventTypeRemoveDomain
:
1018 DomainEventInfo
* domain
;
1019 std::auto_ptr
< DomainEventInfo
> domainAutoPtr
;
1021 domain
= new DomainEventInfo
;
1022 domainAutoPtr
.reset( domain
);
1024 domain
->eventType
= inEvent
->type
;
1025 domain
->domain
= inEvent
->data
.addDomain
.domain
;
1026 domain
->ifIP
= inEvent
->data
.addDomain
.interfaceIP
;
1028 message
= ( inEvent
->type
== kDNSBrowserEventTypeRemoveDomain
) ? WM_USER_DOMAIN_REMOVE
: WM_USER_DOMAIN_ADD
;
1029 posted
= ::PostMessage( dialog
->GetSafeHwnd(), message
, 0, (LPARAM
) domain
);
1033 domainAutoPtr
.release();
1040 case kDNSBrowserEventTypeAddService
:
1041 case kDNSBrowserEventTypeRemoveService
:
1043 ServiceEventInfo
* service
;
1044 std::auto_ptr
< ServiceEventInfo
> serviceAutoPtr
;
1046 service
= new ServiceEventInfo
;
1047 serviceAutoPtr
.reset( service
);
1049 service
->eventType
= inEvent
->type
;
1050 service
->name
= inEvent
->data
.addService
.name
;
1051 service
->type
= inEvent
->data
.addService
.type
;
1052 service
->domain
= inEvent
->data
.addService
.domain
;
1053 service
->ifIP
= inEvent
->data
.addService
.interfaceIP
;
1055 message
= ( inEvent
->type
== kDNSBrowserEventTypeAddService
) ? WM_USER_SERVICE_ADD
: WM_USER_SERVICE_REMOVE
;
1056 posted
= ::PostMessage( dialog
->GetSafeHwnd(), message
, 0, (LPARAM
) service
);
1060 serviceAutoPtr
.release();
1067 case kDNSBrowserEventTypeResolved
:
1069 ServiceInstanceInfo
* serviceInstance
;
1070 std::auto_ptr
< ServiceInstanceInfo
> serviceInstanceAutoPtr
;
1073 serviceInstance
= new ServiceInstanceInfo
;
1074 serviceInstanceAutoPtr
.reset( serviceInstance
);
1076 serviceInstance
->name
= inEvent
->data
.resolved
->name
;
1077 serviceInstance
->type
= inEvent
->data
.resolved
->type
;
1078 serviceInstance
->domain
= inEvent
->data
.resolved
->domain
;
1079 serviceInstance
->ip
= DNSNetworkAddressToString( &inEvent
->data
.resolved
->address
, s
);
1080 serviceInstance
->ifIP
= DNSNetworkAddressToString( &inEvent
->data
.resolved
->interfaceIP
, s
);
1081 serviceInstance
->text
= inEvent
->data
.resolved
->textRecord
;
1083 posted
= ::PostMessage( dialog
->GetSafeHwnd(), WM_USER_RESOLVE
, 0, (LPARAM
) serviceInstance
);
1087 serviceInstanceAutoPtr
.release();
1098 // Don't let exceptions escape.
1102 //===========================================================================================================================
1103 // DNSNetworkAddressToString
1105 // Note: Currently only supports IPv4 network addresses.
1106 //===========================================================================================================================
1108 static char * DNSNetworkAddressToString( const DNSNetworkAddress
*inAddr
, char *outString
)
1113 p
= inAddr
->u
.ipv4
.addr
.v8
;
1114 port
= ntohs( inAddr
->u
.ipv4
.port
.v16
);
1115 if( port
!= kDNSPortInvalid
)
1117 sprintf( outString
, "%u.%u.%u.%u:%u", p
[ 0 ], p
[ 1 ], p
[ 2 ], p
[ 3 ], port
);
1121 sprintf( outString
, "%u.%u.%u.%u", p
[ 0 ], p
[ 1 ], p
[ 2 ], p
[ 3 ] );
1123 return( outString
);
1126 //===========================================================================================================================
1127 // UTF8StringToStringObject
1128 //===========================================================================================================================
1130 static DWORD
UTF8StringToStringObject( const char *inUTF8
, CString
&inObject
)
1138 n
= MultiByteToWideChar( CP_UTF8
, 0, inUTF8
, -1, NULL
, 0 );
1141 unicode
= (BSTR
) malloc( (size_t)( n
* sizeof( wchar_t ) ) );
1144 err
= ERROR_INSUFFICIENT_BUFFER
;
1148 n
= MultiByteToWideChar( CP_UTF8
, 0, inUTF8
, -1, unicode
, n
);
1155 err
= ERROR_NO_UNICODE_TRANSLATION
;