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