]> git.saurik.com Git - apple/mdnsresponder.git/blob - Clients/ExplorerPlugin/ExplorerBarWindow.cpp
mDNSResponder-212.1.tar.gz
[apple/mdnsresponder.git] / Clients / ExplorerPlugin / ExplorerBarWindow.cpp
1 /* -*- Mode: C; tab-width: 4 -*-
2 *
3 * Copyright (c) 2003-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 Change History (most recent first):
18
19 $Log: ExplorerBarWindow.cpp,v $
20 Revision 1.23 2009/03/30 18:47:40 herscher
21 <rdar://problem/5925472> Current Bonjour code does not compile on Windows
22 <rdar://problem/5187308> Move build train to Visual Studio 2005
23
24 Revision 1.22 2006/08/14 23:24:00 cheshire
25 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
26
27 Revision 1.21 2005/04/06 01:13:07 shersche
28 <rdar://problem/4066195> Use the product icon instead of globe icon for 'About' link.
29
30 Revision 1.20 2005/03/18 02:43:02 shersche
31 <rdar://problem/4046443> Use standard IE website icon for 'About Bonjour', only using globe icon if standard icon cannot be loaded
32
33 Revision 1.19 2005/03/16 03:46:27 shersche
34 <rdar://problem/4045657> Use Bonjour icon for all discovered sites
35
36 Revision 1.18 2005/02/26 01:24:05 shersche
37 Remove display lines in tree control
38
39 Revision 1.17 2005/02/25 19:57:30 shersche
40 <rdar://problem/4023323> Remove FTP browsing from plugin
41
42 Revision 1.16 2005/02/08 23:31:06 shersche
43 Move "About ..." item underneath WebSites, change icons for discovered sites and "About ..." item
44
45 Revision 1.15 2005/01/27 22:38:27 shersche
46 add About item to tree list
47
48 Revision 1.14 2005/01/25 17:55:39 shersche
49 <rdar://problem/3911084> Get bitmaps from non-localizable resource module
50 Bug #: 3911084
51
52 Revision 1.13 2005/01/06 21:13:09 shersche
53 <rdar://problem/3796779> Handle kDNSServiceErr_Firewall return codes
54 Bug #: 3796779
55
56 Revision 1.12 2004/10/26 00:56:03 cheshire
57 Use "#if 0" instead of commenting out code
58
59 Revision 1.11 2004/10/18 23:49:17 shersche
60 <rdar://problem/3841564> Remove trailing dot from hostname, because some flavors of Windows have difficulty parsing hostnames with a trailing dot.
61 Bug #: 3841564
62
63 Revision 1.10 2004/09/02 02:18:58 cheshire
64 Minor textual cleanup to improve readability
65
66 Revision 1.9 2004/09/02 02:11:56 cheshire
67 <rdar://problem/3783611> Fix incorrect testing of MoreComing flag
68
69 Revision 1.8 2004/07/26 05:47:31 shersche
70 use TXTRecord APIs, fix bug in locating service to be removed
71
72 Revision 1.7 2004/07/22 16:08:20 shersche
73 clean up debug print statements, re-enable code inadvertently commented out
74
75 Revision 1.6 2004/07/22 05:27:20 shersche
76 <rdar://problem/3735827> Check to make sure error isn't WSAEWOULDBLOCK when canceling browse
77 Bug #: 3735827
78
79 Revision 1.5 2004/07/20 06:49:18 shersche
80 clean up socket handling code
81
82 Revision 1.4 2004/07/13 21:24:21 rpantos
83 Fix for <rdar://problem/3701120>.
84
85 Revision 1.3 2004/06/27 14:59:59 shersche
86 reference count service info to handle multi-homed hosts
87
88 Revision 1.2 2004/06/23 16:09:34 shersche
89 Add the resolve DNSServiceRef to list of extant refs. This fixes the "doesn't resolve when double clicking" problem
90
91 Submitted by: Scott Herscher
92
93 Revision 1.1 2004/06/18 04:34:59 rpantos
94 Move to Clients from mDNSWindows
95
96 Revision 1.5 2004/04/15 01:00:05 bradley
97 Removed support for automatically querying for A/AAAA records when resolving names. Platforms
98 without .local name resolving support will need to manually query for A/AAAA records as needed.
99
100 Revision 1.4 2004/04/09 21:03:15 bradley
101 Changed port numbers to use network byte order for consistency with other platforms.
102
103 Revision 1.3 2004/04/08 09:43:43 bradley
104 Changed callback calling conventions to __stdcall so they can be used with C# delegates.
105
106 Revision 1.2 2004/02/21 04:36:19 bradley
107 Enable dot local name lookups now that the NSP is being installed.
108
109 Revision 1.1 2004/01/30 03:01:56 bradley
110 Explorer Plugin to browse for DNS-SD advertised Web and FTP servers from within Internet Explorer.
111
112 */
113
114 #include "StdAfx.h"
115
116 #include "CommonServices.h"
117 #include "DebugServices.h"
118 #include "WinServices.h"
119 #include "dns_sd.h"
120
121 #include "ExplorerBar.h"
122 #include "LoginDialog.h"
123 #include "Resource.h"
124
125 #include "ExplorerBarWindow.h"
126 #include "ExplorerPlugin.h"
127
128 // MFC Debugging
129
130 #ifdef _DEBUG
131 #define new DEBUG_NEW
132 #undef THIS_FILE
133 static char THIS_FILE[] = __FILE__;
134 #endif
135
136 #if 0
137 #pragma mark == Constants ==
138 #endif
139
140 //===========================================================================================================================
141 // Constants
142 //===========================================================================================================================
143
144 // Control IDs
145
146 #define IDC_EXPLORER_TREE 1234
147
148 // Private Messages
149
150 #define WM_PRIVATE_SERVICE_EVENT ( WM_USER + 0x100 )
151
152 // TXT records
153
154 #define kTXTRecordKeyPath "path"
155
156 // IE Icon resource
157
158 #define kIEIconResource 32529
159
160
161 #if 0
162 #pragma mark == Prototypes ==
163 #endif
164
165 //===========================================================================================================================
166 // Prototypes
167 //===========================================================================================================================
168
169 DEBUG_LOCAL int FindServiceArrayIndex( const ServiceInfoArray &inArray, const ServiceInfo &inService, int &outIndex );
170
171 #if 0
172 #pragma mark == Message Map ==
173 #endif
174
175 //===========================================================================================================================
176 // Message Map
177 //===========================================================================================================================
178
179 BEGIN_MESSAGE_MAP( ExplorerBarWindow, CWnd )
180 ON_WM_CREATE()
181 ON_WM_DESTROY()
182 ON_WM_SIZE()
183 ON_NOTIFY( NM_DBLCLK, IDC_EXPLORER_TREE, OnDoubleClick )
184 ON_MESSAGE( WM_PRIVATE_SERVICE_EVENT, OnServiceEvent )
185 END_MESSAGE_MAP()
186
187 #if 0
188 #pragma mark -
189 #endif
190
191 //===========================================================================================================================
192 // ExplorerBarWindow
193 //===========================================================================================================================
194
195 ExplorerBarWindow::ExplorerBarWindow( void )
196 {
197 mOwner = NULL;
198 mResolveServiceRef = NULL;
199 }
200
201 //===========================================================================================================================
202 // ~ExplorerBarWindow
203 //===========================================================================================================================
204
205 ExplorerBarWindow::~ExplorerBarWindow( void )
206 {
207 //
208 }
209
210 #if 0
211 #pragma mark -
212 #endif
213
214 //===========================================================================================================================
215 // OnCreate
216 //===========================================================================================================================
217
218 int ExplorerBarWindow::OnCreate( LPCREATESTRUCT inCreateStruct )
219 {
220 AFX_MANAGE_STATE( AfxGetStaticModuleState() );
221
222 HINSTANCE module = NULL;
223 OSStatus err;
224 CRect rect;
225 CBitmap bitmap;
226 CString s;
227
228 err = CWnd::OnCreate( inCreateStruct );
229 require_noerr( err, exit );
230
231 GetClientRect( rect );
232 mTree.Create( WS_TABSTOP | WS_VISIBLE | WS_CHILD | TVS_HASBUTTONS | TVS_LINESATROOT | TVS_NOHSCROLL , rect, this,
233 IDC_EXPLORER_TREE );
234
235 ServiceHandlerEntry * e;
236
237 // Web Site Handler
238
239 e = new ServiceHandlerEntry;
240 check( e );
241 e->type = "_http._tcp";
242 e->urlScheme = "http://";
243 e->ref = NULL;
244 e->obj = this;
245 e->needsLogin = false;
246 mServiceHandlers.Add( e );
247
248 s.LoadString( IDS_ABOUT );
249 m_about = mTree.InsertItem( s, 0, 0 );
250
251 err = DNSServiceBrowse( &e->ref, 0, 0, e->type, NULL, BrowseCallBack, e );
252 require_noerr( err, exit );
253
254 err = WSAAsyncSelect((SOCKET) DNSServiceRefSockFD(e->ref), m_hWnd, WM_PRIVATE_SERVICE_EVENT, FD_READ|FD_CLOSE);
255 require_noerr( err, exit );
256
257 m_serviceRefs.push_back(e->ref);
258
259 m_imageList.Create( 16, 16, ILC_MASK | ILC_COLOR16, 2, 0);
260
261 bitmap.Attach( ::LoadBitmap( GetNonLocalizedResources(), MAKEINTRESOURCE( IDB_LOGO ) ) );
262 m_imageList.Add( &bitmap, (CBitmap*) NULL );
263 bitmap.Detach();
264
265 mTree.SetImageList(&m_imageList, TVSIL_NORMAL);
266
267 exit:
268
269 if ( module )
270 {
271 FreeLibrary( module );
272 module = NULL;
273 }
274
275 // Cannot talk to the mDNSResponder service. Show the error message and exit (with kNoErr so they can see it).
276 if ( err )
277 {
278 if ( err == kDNSServiceErr_Firewall )
279 {
280 s.LoadString( IDS_FIREWALL );
281 }
282 else
283 {
284 s.LoadString( IDS_MDNSRESPONDER_NOT_AVAILABLE );
285 }
286
287 mTree.DeleteAllItems();
288 mTree.InsertItem( s, 0, 0, TVI_ROOT, TVI_LAST );
289
290 err = kNoErr;
291 }
292
293 return( err );
294 }
295
296 //===========================================================================================================================
297 // OnDestroy
298 //===========================================================================================================================
299
300 void ExplorerBarWindow::OnDestroy( void )
301 {
302 // Stop any resolves that may still be pending (shouldn't be any).
303
304 StopResolve();
305
306 // Clean up the extant browses
307 while (m_serviceRefs.size() > 0)
308 {
309 //
310 // take the head of the list
311 //
312 DNSServiceRef ref = m_serviceRefs.front();
313
314 //
315 // Stop will remove it from the list
316 //
317 Stop( ref );
318 }
319
320 // Clean up the service handlers.
321
322 int i;
323 int n;
324
325 n = (int) mServiceHandlers.GetSize();
326 for( i = 0; i < n; ++i )
327 {
328 delete mServiceHandlers[ i ];
329 }
330
331 CWnd::OnDestroy();
332 }
333
334 //===========================================================================================================================
335 // OnSize
336 //===========================================================================================================================
337
338 void ExplorerBarWindow::OnSize( UINT inType, int inX, int inY )
339 {
340 CWnd::OnSize( inType, inX, inY );
341 mTree.MoveWindow( 0, 0, inX, inY );
342 }
343
344 //===========================================================================================================================
345 // OnDoubleClick
346 //===========================================================================================================================
347
348 void ExplorerBarWindow::OnDoubleClick( NMHDR *inNMHDR, LRESULT *outResult )
349 {
350 HTREEITEM item;
351 ServiceInfo * service;
352 OSStatus err;
353
354 DEBUG_UNUSED( inNMHDR );
355
356 item = mTree.GetSelectedItem();
357 require( item, exit );
358
359 // Tell Internet Explorer to go to the URL if it's about item
360
361 if ( item == m_about )
362 {
363 CString url;
364
365 check( mOwner );
366
367 url.LoadString( IDS_ABOUT_URL );
368 mOwner->GoToURL( url );
369 }
370 else
371 {
372 service = reinterpret_cast < ServiceInfo * > ( mTree.GetItemData( item ) );
373 require_quiet( service, exit );
374
375 err = StartResolve( service );
376 require_noerr( err, exit );
377 }
378
379 exit:
380 *outResult = 0;
381 }
382
383
384 //===========================================================================================================================
385 // OnServiceEvent
386 //===========================================================================================================================
387
388 LRESULT
389 ExplorerBarWindow::OnServiceEvent(WPARAM inWParam, LPARAM inLParam)
390 {
391 if (WSAGETSELECTERROR(inLParam) && !(HIWORD(inLParam)))
392 {
393 dlog( kDebugLevelError, "OnServiceEvent: window error\n" );
394 }
395 else
396 {
397 SOCKET sock = (SOCKET) inWParam;
398
399 // iterate thru list
400 ServiceRefList::iterator it;
401
402 for (it = m_serviceRefs.begin(); it != m_serviceRefs.end(); it++)
403 {
404 DNSServiceRef ref = *it;
405
406 check(ref != NULL);
407
408 if ((SOCKET) DNSServiceRefSockFD(ref) == sock)
409 {
410 DNSServiceErrorType err;
411
412 err = DNSServiceProcessResult(ref);
413
414 if (err != 0)
415 {
416 CString s;
417
418 s.LoadString( IDS_MDNSRESPONDER_NOT_AVAILABLE );
419 mTree.DeleteAllItems();
420 mTree.InsertItem( s, 0, 0, TVI_ROOT, TVI_LAST );
421
422 Stop(ref);
423 }
424
425 break;
426 }
427 }
428 }
429
430 return ( 0 );
431 }
432
433 #if 0
434 #pragma mark -
435 #endif
436
437 //===========================================================================================================================
438 // BrowseCallBack
439 //===========================================================================================================================
440
441 void DNSSD_API
442 ExplorerBarWindow::BrowseCallBack(
443 DNSServiceRef inRef,
444 DNSServiceFlags inFlags,
445 uint32_t inInterfaceIndex,
446 DNSServiceErrorType inErrorCode,
447 const char * inName,
448 const char * inType,
449 const char * inDomain,
450 void * inContext )
451 {
452 ServiceHandlerEntry * obj;
453 ServiceInfo * service;
454 OSStatus err;
455
456 DEBUG_UNUSED( inRef );
457
458 obj = NULL;
459 service = NULL;
460
461 require_noerr( inErrorCode, exit );
462 obj = reinterpret_cast < ServiceHandlerEntry * > ( inContext );
463 check( obj );
464 check( obj->obj );
465
466 //
467 // set the UI to hold off on updates
468 //
469 obj->obj->mTree.SetRedraw(FALSE);
470
471 try
472 {
473 service = new ServiceInfo;
474 require_action( service, exit, err = kNoMemoryErr );
475
476 err = UTF8StringToStringObject( inName, service->displayName );
477 check_noerr( err );
478
479 service->name = _strdup( inName );
480 require_action( service->name, exit, err = kNoMemoryErr );
481
482 service->type = _strdup( inType );
483 require_action( service->type, exit, err = kNoMemoryErr );
484
485 service->domain = _strdup( inDomain );
486 require_action( service->domain, exit, err = kNoMemoryErr );
487
488 service->ifi = inInterfaceIndex;
489 service->handler = obj;
490
491 service->refs = 1;
492
493 if (inFlags & kDNSServiceFlagsAdd) obj->obj->OnServiceAdd (service);
494 else obj->obj->OnServiceRemove(service);
495
496 service = NULL;
497 }
498 catch( ... )
499 {
500 dlog( kDebugLevelError, "BrowseCallBack: exception thrown\n" );
501 }
502
503 exit:
504 //
505 // If no more coming, then update UI
506 //
507 if (obj && obj->obj && ((inFlags & kDNSServiceFlagsMoreComing) == 0))
508 {
509 obj->obj->mTree.SetRedraw(TRUE);
510 obj->obj->mTree.Invalidate();
511 }
512
513 if( service )
514 {
515 delete service;
516 }
517 }
518
519 //===========================================================================================================================
520 // OnServiceAdd
521 //===========================================================================================================================
522
523 LONG ExplorerBarWindow::OnServiceAdd( ServiceInfo * service )
524 {
525 ServiceHandlerEntry * handler;
526 int cmp;
527 int index;
528
529
530 check( service );
531 handler = service->handler;
532 check( handler );
533
534 cmp = FindServiceArrayIndex( handler->array, *service, index );
535 if( cmp == 0 )
536 {
537 // Found a match so update the item. The index is index + 1 so subtract 1.
538
539 index -= 1;
540 check( index < handler->array.GetSize() );
541
542 handler->array[ index ]->refs++;
543
544 delete service;
545 }
546 else
547 {
548 HTREEITEM afterItem;
549
550 // Insert the new item in sorted order.
551
552 afterItem = ( index > 0 ) ? handler->array[ index - 1 ]->item : m_about;
553 handler->array.InsertAt( index, service );
554 service->item = mTree.InsertItem( service->displayName, 0, 0, NULL, afterItem );
555 mTree.SetItemData( service->item, (DWORD_PTR) service );
556 }
557 return( 0 );
558 }
559
560 //===========================================================================================================================
561 // OnServiceRemove
562 //===========================================================================================================================
563
564 LONG ExplorerBarWindow::OnServiceRemove( ServiceInfo * service )
565 {
566 ServiceHandlerEntry * handler;
567 int cmp;
568 int index;
569
570
571 check( service );
572 handler = service->handler;
573 check( handler );
574
575 // Search to see if we know about this service instance. If so, remove it from the list.
576
577 cmp = FindServiceArrayIndex( handler->array, *service, index );
578 check( cmp == 0 );
579
580 if( cmp == 0 )
581 {
582 // Possibly found a match remove the item. The index
583 // is index + 1 so subtract 1.
584 index -= 1;
585 check( index < handler->array.GetSize() );
586
587 if ( --handler->array[ index ]->refs == 0 )
588 {
589 mTree.DeleteItem( handler->array[ index ]->item );
590 delete handler->array[ index ];
591 handler->array.RemoveAt( index );
592 }
593 }
594
595 delete service;
596 return( 0 );
597 }
598
599 #if 0
600 #pragma mark -
601 #endif
602
603 //===========================================================================================================================
604 // StartResolve
605 //===========================================================================================================================
606
607 OSStatus ExplorerBarWindow::StartResolve( ServiceInfo *inService )
608 {
609 OSStatus err;
610
611 check( inService );
612
613 // Stop any current resolve that may be in progress.
614
615 StopResolve();
616
617 // Resolve the service.
618 err = DNSServiceResolve( &mResolveServiceRef, 0, 0,
619 inService->name, inService->type, inService->domain, (DNSServiceResolveReply) ResolveCallBack, inService->handler );
620 require_noerr( err, exit );
621
622 err = WSAAsyncSelect((SOCKET) DNSServiceRefSockFD(mResolveServiceRef), m_hWnd, WM_PRIVATE_SERVICE_EVENT, FD_READ|FD_CLOSE);
623 require_noerr( err, exit );
624
625 m_serviceRefs.push_back(mResolveServiceRef);
626
627 exit:
628 return( err );
629 }
630
631 //===========================================================================================================================
632 // StopResolve
633 //===========================================================================================================================
634
635 void ExplorerBarWindow::StopResolve( void )
636 {
637 if( mResolveServiceRef )
638 {
639 Stop( mResolveServiceRef );
640 mResolveServiceRef = NULL;
641 }
642 }
643
644 //===========================================================================================================================
645 // ResolveCallBack
646 //===========================================================================================================================
647
648 void DNSSD_API
649 ExplorerBarWindow::ResolveCallBack(
650 DNSServiceRef inRef,
651 DNSServiceFlags inFlags,
652 uint32_t inInterfaceIndex,
653 DNSServiceErrorType inErrorCode,
654 const char * inFullName,
655 const char * inHostName,
656 uint16_t inPort,
657 uint16_t inTXTSize,
658 const char * inTXT,
659 void * inContext )
660 {
661 ExplorerBarWindow * obj;
662 ServiceHandlerEntry * handler;
663 OSStatus err;
664
665 DEBUG_UNUSED( inRef );
666 DEBUG_UNUSED( inFlags );
667 DEBUG_UNUSED( inErrorCode );
668 DEBUG_UNUSED( inFullName );
669
670 require_noerr( inErrorCode, exit );
671 handler = (ServiceHandlerEntry *) inContext;
672 check( handler );
673 obj = handler->obj;
674 check( obj );
675
676 try
677 {
678 ResolveInfo * resolve;
679 int idx;
680
681 dlog( kDebugLevelNotice, "resolved %s on ifi %d to %s\n", inFullName, inInterfaceIndex, inHostName );
682
683 // Stop resolving after the first good result.
684
685 obj->StopResolve();
686
687 // Post a message to the main thread so it can handle it since MFC is not thread safe.
688
689 resolve = new ResolveInfo;
690 require_action( resolve, exit, err = kNoMemoryErr );
691
692 UTF8StringToStringObject( inHostName, resolve->host );
693
694 // rdar://problem/3841564
695 //
696 // strip trailing dot from hostname because some flavors of Windows
697 // have trouble parsing it.
698
699 idx = resolve->host.ReverseFind('.');
700
701 if ((idx > 1) && ((resolve->host.GetLength() - 1) == idx))
702 {
703 resolve->host.Delete(idx, 1);
704 }
705
706 resolve->port = ntohs( inPort );
707 resolve->ifi = inInterfaceIndex;
708 resolve->handler = handler;
709
710 err = resolve->txt.SetData( inTXT, inTXTSize );
711 check_noerr( err );
712
713 obj->OnResolve(resolve);
714 }
715 catch( ... )
716 {
717 dlog( kDebugLevelError, "ResolveCallBack: exception thrown\n" );
718 }
719
720 exit:
721 return;
722 }
723
724 //===========================================================================================================================
725 // OnResolve
726 //===========================================================================================================================
727
728 LONG ExplorerBarWindow::OnResolve( ResolveInfo * resolve )
729 {
730 CString url;
731 uint8_t * path;
732 uint8_t pathSize;
733 char * pathPrefix;
734 CString username;
735 CString password;
736
737
738 check( resolve );
739
740 // Get login info if needed.
741
742 if( resolve->handler->needsLogin )
743 {
744 LoginDialog dialog;
745
746 if( !dialog.GetLogin( username, password ) )
747 {
748 goto exit;
749 }
750 }
751
752 // If the HTTP TXT record is a "path=" entry, use it as the resource path. Otherwise, use "/".
753
754 pathPrefix = "";
755 if( strcmp( resolve->handler->type, "_http._tcp" ) == 0 )
756 {
757 uint8_t * txtData;
758 uint16_t txtLen;
759
760 resolve->txt.GetData( &txtData, &txtLen );
761
762 path = (uint8_t*) TXTRecordGetValuePtr(txtLen, txtData, kTXTRecordKeyPath, &pathSize);
763
764 if (path == NULL)
765 {
766 path = (uint8_t*) "";
767 pathSize = 1;
768 }
769 }
770 else
771 {
772 path = (uint8_t *) "";
773 pathSize = 1;
774 }
775
776 // Build the URL in the following format:
777 //
778 // <urlScheme>[<username>[:<password>]@]<name/ip>[<path>]
779
780 url.AppendFormat( TEXT( "%S" ), resolve->handler->urlScheme ); // URL Scheme
781 if( username.GetLength() > 0 )
782 {
783 url.AppendFormat( TEXT( "%s" ), username ); // Username
784 if( password.GetLength() > 0 )
785 {
786 url.AppendFormat( TEXT( ":%s" ), password ); // Password
787 }
788 url.AppendFormat( TEXT( "@" ) );
789 }
790
791 url += resolve->host; // Host
792 url.AppendFormat( TEXT( ":%d" ), resolve->port ); // :Port
793 url.AppendFormat( TEXT( "%S" ), pathPrefix ); // Path Prefix ("/" or empty).
794 url.AppendFormat( TEXT( "%.*S" ), (int) pathSize, (char *) path ); // Path (possibly empty).
795
796 // Tell Internet Explorer to go to the URL.
797
798 check( mOwner );
799 mOwner->GoToURL( url );
800
801 exit:
802 delete resolve;
803 return( 0 );
804 }
805
806 //===========================================================================================================================
807 // Stop
808 //===========================================================================================================================
809 void ExplorerBarWindow::Stop( DNSServiceRef ref )
810 {
811 m_serviceRefs.remove( ref );
812
813 WSAAsyncSelect(DNSServiceRefSockFD( ref ), m_hWnd, WM_PRIVATE_SERVICE_EVENT, 0);
814
815 DNSServiceRefDeallocate( ref );
816 }
817
818
819 #if 0
820 #pragma mark -
821 #endif
822
823 //===========================================================================================================================
824 // FindServiceArrayIndex
825 //===========================================================================================================================
826
827 DEBUG_LOCAL int FindServiceArrayIndex( const ServiceInfoArray &inArray, const ServiceInfo &inService, int &outIndex )
828 {
829 int result;
830 int lo;
831 int hi;
832 int mid;
833
834 result = -1;
835 mid = 0;
836 lo = 0;
837 hi = (int)( inArray.GetSize() - 1 );
838 while( lo <= hi )
839 {
840 mid = ( lo + hi ) / 2;
841 result = inService.displayName.CompareNoCase( inArray[ mid ]->displayName );
842 #if 0
843 if( result == 0 )
844 {
845 result = ( (int) inService.ifi ) - ( (int) inArray[ mid ]->ifi );
846 }
847 #endif
848 if( result == 0 )
849 {
850 break;
851 }
852 else if( result < 0 )
853 {
854 hi = mid - 1;
855 }
856 else
857 {
858 lo = mid + 1;
859 }
860 }
861 if( result == 0 )
862 {
863 mid += 1; // Bump index so new item is inserted after matching item.
864 }
865 else if( result > 0 )
866 {
867 mid += 1;
868 }
869 outIndex = mid;
870 return( result );
871 }