2 * Copyright (c) 2003-2004 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):
26 Revision 1.6 2004/12/06 01:56:53 shersche
27 <rdar://problem/3789425> Use the DNS types and classes defined in dns_sd.h
30 Revision 1.5 2004/07/13 21:24:28 rpantos
31 Fix for <rdar://problem/3701120>.
33 Revision 1.4 2004/07/09 18:03:33 shersche
34 removed extraneous DNSServiceQueryRecord call
36 Revision 1.3 2004/07/07 17:03:49 shersche
37 <rdar://problem/3715582> Check for LUP_RETURN_ADDR as well as LUP_RETURN_BLOB in NSPLookupServiceBegin
40 Revision 1.2 2004/06/24 19:18:07 shersche
42 Submitted by: herscher
44 Revision 1.1 2004/06/18 04:13:44 rpantos
47 Revision 1.2 2004/04/08 09:43:43 bradley
48 Changed callback calling conventions to __stdcall so they can be used with C# delegates.
50 Revision 1.1 2004/01/30 03:00:33 bradley
51 mDNS NameSpace Provider (NSP). Hooks into the Windows name resolution system to perform
52 .local name lookups using Multicast DNS in all Windows apps.
60 #include "CommonServices.h"
61 #include "DebugServices.h"
69 #pragma mark == Structures ==
72 //===========================================================================================================================
74 //===========================================================================================================================
76 typedef struct Query
* QueryRef
;
77 typedef struct Query Query
;
83 WSAQUERYSETW
* querySet
;
87 HANDLE waitHandles
[ 2 ];
89 DNSServiceRef resolver
;
90 char name
[ kDNSServiceMaxDomainName
];
97 #pragma mark == Prototypes ==
100 //===========================================================================================================================
102 //===========================================================================================================================
106 BOOL WINAPI
DllMain( HINSTANCE inInstance
, DWORD inReason
, LPVOID inReserved
);
110 int WSPAPI
NSPCleanup( LPGUID inProviderID
);
112 DEBUG_LOCAL
int WSPAPI
113 NSPLookupServiceBegin(
115 LPWSAQUERYSETW inQuerySet
,
116 LPWSASERVICECLASSINFOW inServiceClassInfo
,
118 LPHANDLE outLookup
);
120 DEBUG_LOCAL
int WSPAPI
121 NSPLookupServiceNext(
124 LPDWORD ioBufferLength
,
125 LPWSAQUERYSETW outResults
);
127 DEBUG_LOCAL
int WSPAPI
NSPLookupServiceEnd( HANDLE inLookup
);
129 DEBUG_LOCAL
int WSPAPI
132 LPWSASERVICECLASSINFOW inServiceClassInfo
,
133 LPWSAQUERYSETW inRegInfo
,
134 WSAESETSERVICEOP inOperation
,
137 DEBUG_LOCAL
int WSPAPI
NSPInstallServiceClass( LPGUID inProviderID
, LPWSASERVICECLASSINFOW inServiceClassInfo
);
138 DEBUG_LOCAL
int WSPAPI
NSPRemoveServiceClass( LPGUID inProviderID
, LPGUID inServiceClassID
);
139 DEBUG_LOCAL
int WSPAPI
NSPGetServiceClassInfo( LPGUID inProviderID
, LPDWORD ioBufSize
, LPWSASERVICECLASSINFOW ioServiceClassInfo
);
143 #define NSPLock() EnterCriticalSection( &gLock );
144 #define NSPUnlock() LeaveCriticalSection( &gLock );
146 DEBUG_LOCAL OSStatus
QueryCreate( const WSAQUERYSETW
*inQuerySet
, DWORD inQuerySetFlags
, QueryRef
*outRef
);
147 DEBUG_LOCAL OSStatus
QueryRetain( QueryRef inRef
);
148 DEBUG_LOCAL OSStatus
QueryRelease( QueryRef inRef
);
150 DEBUG_LOCAL
void CALLBACK_COMPAT
153 DNSServiceFlags inFlags
,
154 uint32_t inInterfaceIndex
,
155 DNSServiceErrorType inErrorCode
,
159 uint16_t inRDataSize
,
160 const void * inRData
,
167 const WSAQUERYSETW
* inQuerySet
,
168 DWORD inQuerySetFlags
,
169 WSAQUERYSETW
** outQuerySet
,
175 const WSAQUERYSETW
* inQuerySet
,
176 DWORD inQuerySetFlags
,
177 WSAQUERYSETW
* outQuerySet
);
179 DEBUG_LOCAL
size_t QueryCopyQuerySetSize( QueryRef inRef
, const WSAQUERYSETW
*inQuerySet
, DWORD inQuerySetFlags
);
182 void DebugDumpQuerySet( DebugLevel inLevel
, const WSAQUERYSETW
*inQuerySet
);
184 #define dlog_query_set( LEVEL, SET ) DebugDumpQuerySet( LEVEL, SET )
186 #define dlog_query_set( LEVEL, SET )
190 #pragma mark == Globals ==
193 //===========================================================================================================================
195 //===========================================================================================================================
197 // {B600E6E9-553B-4a19-8696-335E5C896153}
198 // GUID kmdnsNSPGUID = { 0xb600e6e9, 0x553b, 0x4a19, { 0x86, 0x96, 0x33, 0x5e, 0x5c, 0x89, 0x61, 0x53 } };
200 DEBUG_LOCAL LONG gRefCount
= 0;
201 DEBUG_LOCAL CRITICAL_SECTION gLock
;
202 DEBUG_LOCAL
bool gLockInitialized
= false;
203 DEBUG_LOCAL
bool gDNSSDInitialized
= false;
204 DEBUG_LOCAL QueryRef gQueryList
= NULL
;
210 //===========================================================================================================================
212 //===========================================================================================================================
214 BOOL APIENTRY
DllMain( HINSTANCE inInstance
, DWORD inReason
, LPVOID inReserved
)
216 DEBUG_USE_ONLY( inInstance
);
217 DEBUG_UNUSED( inReserved
);
221 case DLL_PROCESS_ATTACH
:
222 debug_initialize( kDebugOutputTypeWindowsEventLog
, "mDNS NSP", inInstance
);
223 debug_set_property( kDebugPropertyTagPrintLevel
, kDebugLevelInfo
);
224 dlog( kDebugLevelTrace
, "\n" );
225 dlog( kDebugLevelVerbose
, "%s: process attach\n", __ROUTINE__
);
228 case DLL_PROCESS_DETACH
:
229 dlog( kDebugLevelVerbose
, "%s: process detach\n", __ROUTINE__
);
232 case DLL_THREAD_ATTACH
:
233 dlog( kDebugLevelVerbose
, "%s: thread attach\n", __ROUTINE__
);
236 case DLL_THREAD_DETACH
:
237 dlog( kDebugLevelVerbose
, "%s: thread detach\n", __ROUTINE__
);
241 dlog( kDebugLevelNotice
, "%s: unknown reason code (%d)\n", __ROUTINE__
, inReason
);
247 //===========================================================================================================================
250 // This function is called when our namespace DLL is loaded. It sets up the NSP functions we implement and initializes us.
251 //===========================================================================================================================
253 int WSPAPI
NSPStartup( LPGUID inProviderID
, LPNSP_ROUTINE outRoutines
)
257 dlog( kDebugLevelTrace
, "%s begin (ticks=%d)\n", __ROUTINE__
, GetTickCount() );
258 dlog( kDebugLevelTrace
, "%s (GUID=%U, refCount=%ld)\n", __ROUTINE__
, inProviderID
, gRefCount
);
260 // Only initialize if this is the first time NSPStartup is called.
262 if( InterlockedIncrement( &gRefCount
) != 1 )
268 // Initialize our internal state.
270 InitializeCriticalSection( &gLock
);
271 gLockInitialized
= true;
273 // Set the size to exclude NSPIoctl because we don't implement it.
275 outRoutines
->cbSize
= FIELD_OFFSET( NSP_ROUTINE
, NSPIoctl
);
276 outRoutines
->dwMajorVersion
= 4;
277 outRoutines
->dwMinorVersion
= 4;
278 outRoutines
->NSPCleanup
= NSPCleanup
;
279 outRoutines
->NSPLookupServiceBegin
= NSPLookupServiceBegin
;
280 outRoutines
->NSPLookupServiceNext
= NSPLookupServiceNext
;
281 outRoutines
->NSPLookupServiceEnd
= NSPLookupServiceEnd
;
282 outRoutines
->NSPSetService
= NSPSetService
;
283 outRoutines
->NSPInstallServiceClass
= NSPInstallServiceClass
;
284 outRoutines
->NSPRemoveServiceClass
= NSPRemoveServiceClass
;
285 outRoutines
->NSPGetServiceClassInfo
= NSPGetServiceClassInfo
;
290 dlog( kDebugLevelTrace
, "%s end (ticks=%d)\n", __ROUTINE__
, GetTickCount() );
291 if( err
!= NO_ERROR
)
293 NSPCleanup( inProviderID
);
294 SetLastError( (DWORD
) err
);
295 return( SOCKET_ERROR
);
300 //===========================================================================================================================
303 // This function is called when our namespace DLL is unloaded. It cleans up anything we set up in NSPStartup.
304 //===========================================================================================================================
306 int WSPAPI
NSPCleanup( LPGUID inProviderID
)
308 DEBUG_USE_ONLY( inProviderID
);
310 dlog( kDebugLevelTrace
, "%s begin (ticks=%d)\n", __ROUTINE__
, GetTickCount() );
311 dlog( kDebugLevelTrace
, "%s (GUID=%U, refCount=%ld)\n", __ROUTINE__
, inProviderID
, gRefCount
);
313 // Only initialize if this is the first time NSPStartup is called.
315 if( InterlockedDecrement( &gRefCount
) != 0 )
320 // Stop any outstanding queries.
322 if( gLockInitialized
)
328 check_string( gQueryList
->refCount
== 1, "NSPCleanup with outstanding queries!" );
329 QueryRelease( gQueryList
);
331 if( gLockInitialized
)
336 // Shut down DNS-SD and release our resources.
338 if( gDNSSDInitialized
)
340 gDNSSDInitialized
= false;
342 if( gLockInitialized
)
344 gLockInitialized
= false;
345 DeleteCriticalSection( &gLock
);
349 dlog( kDebugLevelTrace
, "%s end (ticks=%d)\n", __ROUTINE__
, GetTickCount() );
353 //===========================================================================================================================
354 // NSPLookupServiceBegin
356 // This function maps to the WinSock WSALookupServiceBegin function. It starts the lookup process and returns a HANDLE
357 // that can be used in subsequent operations. Subsequent calls only need to refer to this query by the handle as
358 // opposed to specifying the query parameters each time.
359 //===========================================================================================================================
361 DEBUG_LOCAL
int WSPAPI
362 NSPLookupServiceBegin(
364 LPWSAQUERYSETW inQuerySet
,
365 LPWSASERVICECLASSINFOW inServiceClassInfo
,
380 DEBUG_UNUSED( inProviderID
);
381 DEBUG_UNUSED( inServiceClassInfo
);
383 dlog( kDebugLevelTrace
, "%s begin (ticks=%d)\n", __ROUTINE__
, GetTickCount() );
386 require_action( inQuerySet
, exit
, err
= WSAEINVAL
);
387 name
= inQuerySet
->lpszServiceInstanceName
;
388 require_action_quiet( name
, exit
, err
= WSAEINVAL
);
389 require_action( outLookup
, exit
, err
= WSAEINVAL
);
391 dlog( kDebugLevelTrace
, "%s (flags=0x%08X, name=\"%S\")\n", __ROUTINE__
, inFlags
, name
);
392 dlog_query_set( kDebugLevelVerbose
, inQuerySet
);
394 // Check if we can handle this type of request and if we support any of the protocols being requested.
395 // We only support the DNS namespace, TCP and UDP protocols, and IPv4. Only blob results are supported.
397 require_action_quiet( inFlags
& (LUP_RETURN_ADDR
|LUP_RETURN_BLOB
), exit
, err
= WSASERVICE_NOT_FOUND
);
399 type
= inQuerySet
->dwNameSpace
;
400 require_action_quiet( ( type
== NS_DNS
) || ( type
== NS_ALL
), exit
, err
= WSASERVICE_NOT_FOUND
);
402 n
= inQuerySet
->dwNumberOfProtocols
;
405 require_action( inQuerySet
->lpafpProtocols
, exit
, err
= WSAEINVAL
);
406 for( i
= 0; i
< n
; ++i
)
408 family
= inQuerySet
->lpafpProtocols
[ i
].iAddressFamily
;
409 protocol
= inQuerySet
->lpafpProtocols
[ i
].iProtocol
;
410 if( ( family
== AF_INET
) && ( ( protocol
== IPPROTO_UDP
) || ( protocol
== IPPROTO_TCP
) ) )
415 require_action_quiet( i
< n
, exit
, err
= WSASERVICE_NOT_FOUND
);
418 // Check if the name ends in ".local" and if not, exit with an error since we only resolve .local names.
419 // The name may or may not end with a "." (fully qualified) so handle both cases. DNS is also case
420 // insensitive the check for .local has to be case insensitive (.LoCaL is equivalent to .local). This
421 // manually does the wchar_t strlen and stricmp to avoid needing any special wchar_t versions of the
422 // libraries. It is probably faster to do the inline compare than invoke functions to do it anyway.
424 for( p
= name
; *p
; ++p
) {} // Find end of string
425 size
= (size_t)( p
- name
);
426 require_action_quiet( size
> sizeof_string( ".local" ), exit
, err
= WSASERVICE_NOT_FOUND
);
428 p
= name
+ ( size
- 1 );
429 p
= ( *p
== '.' ) ? ( p
- sizeof_string( ".local" ) ) : ( ( p
- sizeof_string( ".local" ) ) + 1 );
430 if ( ( ( p
[ 0 ] != '.' ) ||
431 ( ( p
[ 1 ] != 'L' ) && ( p
[ 1 ] != 'l' ) ) ||
432 ( ( p
[ 2 ] != 'O' ) && ( p
[ 2 ] != 'o' ) ) ||
433 ( ( p
[ 3 ] != 'C' ) && ( p
[ 3 ] != 'c' ) ) ||
434 ( ( p
[ 4 ] != 'A' ) && ( p
[ 4 ] != 'a' ) ) ||
435 ( ( p
[ 5 ] != 'L' ) && ( p
[ 5 ] != 'l' ) ) ) )
437 require_action_quiet( size
> sizeof_string( ".0.8.e.f.ip6.arpa" ), exit
, err
= WSASERVICE_NOT_FOUND
);
439 p
= name
+ ( size
- 1 );
440 p
= ( *p
== '.' ) ? ( p
- sizeof_string( ".0.8.e.f.ip6.arpa" ) ) : ( ( p
- sizeof_string( ".0.8.e.f.ip6.arpa" ) ) + 1 );
442 if ( ( ( p
[ 0 ] != '.' ) ||
443 ( ( p
[ 1 ] != '0' ) ) ||
444 ( ( p
[ 2 ] != '.' ) ) ||
445 ( ( p
[ 3 ] != '8' ) ) ||
446 ( ( p
[ 4 ] != '.' ) ) ||
447 ( ( p
[ 5 ] != 'E' ) && ( p
[ 5 ] != 'e' ) ) ||
448 ( ( p
[ 6 ] != '.' ) ) ||
449 ( ( p
[ 7 ] != 'F' ) && ( p
[ 7 ] != 'f' ) ) ||
450 ( ( p
[ 8 ] != '.' ) ) ||
451 ( ( p
[ 9 ] != 'I' ) && ( p
[ 9 ] != 'i' ) ) ||
452 ( ( p
[ 10 ] != 'P' ) && ( p
[ 10 ] != 'p' ) ) ||
453 ( ( p
[ 11 ] != '6' ) ) ||
454 ( ( p
[ 12 ] != '.' ) ) ||
455 ( ( p
[ 13 ] != 'A' ) && ( p
[ 13 ] != 'a' ) ) ||
456 ( ( p
[ 14 ] != 'R' ) && ( p
[ 14 ] != 'r' ) ) ||
457 ( ( p
[ 15 ] != 'P' ) && ( p
[ 15 ] != 'p' ) ) ||
458 ( ( p
[ 16 ] != 'A' ) && ( p
[ 16 ] != 'a' ) ) ) )
460 require_action_quiet( size
> sizeof_string( ".254.169.in-addr.arpa" ), exit
, err
= WSASERVICE_NOT_FOUND
);
462 p
= name
+ ( size
- 1 );
463 p
= ( *p
== '.' ) ? ( p
- sizeof_string( ".254.169.in-addr.arpa" ) ) : ( ( p
- sizeof_string( ".254.169.in-addr.arpa" ) ) + 1 );
465 require_action_quiet( ( ( p
[ 0 ] == '.' ) &&
466 ( ( p
[ 1 ] == '2' ) ) &&
467 ( ( p
[ 2 ] == '5' ) ) &&
468 ( ( p
[ 3 ] == '4' ) ) &&
469 ( ( p
[ 4 ] == '.' ) ) &&
470 ( ( p
[ 5 ] == '1' ) ) &&
471 ( ( p
[ 6 ] == '6' ) ) &&
472 ( ( p
[ 7 ] == '9' ) ) &&
473 ( ( p
[ 8 ] == '.' ) ) &&
474 ( ( p
[ 9 ] == 'I' ) || ( p
[ 9 ] == 'i' ) ) &&
475 ( ( p
[ 10 ] == 'N' ) || ( p
[ 10 ] == 'n' ) ) &&
476 ( ( p
[ 11 ] == '-' ) ) &&
477 ( ( p
[ 12 ] == 'A' ) || ( p
[ 12 ] == 'a' ) ) &&
478 ( ( p
[ 13 ] == 'D' ) || ( p
[ 13 ] == 'd' ) ) &&
479 ( ( p
[ 14 ] == 'D' ) || ( p
[ 14 ] == 'd' ) ) &&
480 ( ( p
[ 15 ] == 'R' ) || ( p
[ 15 ] == 'r' ) ) &&
481 ( ( p
[ 16 ] == '.' ) ) &&
482 ( ( p
[ 17 ] == 'A' ) || ( p
[ 17 ] == 'a' ) ) &&
483 ( ( p
[ 18 ] == 'R' ) || ( p
[ 18 ] == 'r' ) ) &&
484 ( ( p
[ 19 ] == 'P' ) || ( p
[ 19 ] == 'p' ) ) &&
485 ( ( p
[ 20 ] == 'A' ) || ( p
[ 20 ] == 'a' ) ) ),
486 exit
, err
= WSASERVICE_NOT_FOUND
);
490 // The name ends in .local, .0.8.e.f.ip6.arpa, or .254.169.in-addr.arpa so start the resolve operation. Lazy initialize DNS-SD if needed.
493 if( !gDNSSDInitialized
)
495 gDNSSDInitialized
= true;
498 err
= QueryCreate( inQuerySet
, inFlags
, &obj
);
500 require_noerr( err
, exit
);
502 *outLookup
= (HANDLE
) obj
;
505 dlog( kDebugLevelTrace
, "%s end (ticks=%d)\n", __ROUTINE__
, GetTickCount() );
506 if( err
!= NO_ERROR
)
508 SetLastError( (DWORD
) err
);
509 return( SOCKET_ERROR
);
514 //===========================================================================================================================
515 // NSPLookupServiceNext
517 // This function maps to the Winsock call WSALookupServiceNext. This routine takes a handle to a previously defined
518 // query and attempts to locate a service matching the criteria defined by the query. If so, that instance is returned
519 // in the lpqsResults parameter.
520 //===========================================================================================================================
522 DEBUG_LOCAL
int WSPAPI
523 NSPLookupServiceNext(
527 LPWSAQUERYSETW outResults
)
534 DEBUG_USE_ONLY( inFlags
);
536 dlog( kDebugLevelTrace
, "%s begin (ticks=%d)\n", __ROUTINE__
, GetTickCount() );
540 err
= QueryRetain( (QueryRef
) inLookup
);
541 require_noerr( err
, exit
);
542 obj
= (QueryRef
) inLookup
;
543 require_action( ioSize
, exit
, err
= WSAEINVAL
);
544 require_action( outResults
, exit
, err
= WSAEINVAL
);
546 dlog( kDebugLevelTrace
, "%s (lookup=%#p, flags=0x%08X, *ioSize=%d)\n", __ROUTINE__
, inLookup
, inFlags
, *ioSize
);
548 // Wait for data or a cancel. Release the lock while waiting. This is safe because we've retained the query.
551 waitResult
= WaitForMultipleObjects( obj
->waitCount
, obj
->waitHandles
, FALSE
, 5 * 1000 );
553 require_action_quiet( waitResult
!= ( WAIT_OBJECT_0
+ 1 ), exit
, err
= WSA_E_CANCELLED
);
554 err
= translate_errno( waitResult
== WAIT_OBJECT_0
, (OSStatus
) GetLastError(), WSASERVICE_NOT_FOUND
);
555 require_noerr_quiet( err
, exit
);
556 DNSServiceProcessResult(obj
->resolver
);
557 require_action_quiet( obj
->addrValid
, exit
, err
= WSA_E_NO_MORE
);
559 // Copy the externalized query results to the callers buffer (if it fits).
561 size
= QueryCopyQuerySetSize( obj
, obj
->querySet
, obj
->querySetFlags
);
562 require_action( size
<= (size_t) *ioSize
, exit
, err
= WSAEFAULT
);
564 QueryCopyQuerySetTo( obj
, obj
->querySet
, obj
->querySetFlags
, outResults
);
565 outResults
->dwOutputFlags
= RESULT_IS_ADDED
;
566 obj
->addrValid
= false;
574 dlog( kDebugLevelTrace
, "%s end (ticks=%d)\n", __ROUTINE__
, GetTickCount() );
575 if( err
!= NO_ERROR
)
577 SetLastError( (DWORD
) err
);
578 return( SOCKET_ERROR
);
583 //===========================================================================================================================
584 // NSPLookupServiceEnd
586 // This function maps to the Winsock call WSALookupServiceEnd. Once the user process has finished is query (usually
587 // indicated when WSALookupServiceNext returns the error WSA_E_NO_MORE) a call to this function is made to release any
588 // allocated resources associated with the query.
589 //===========================================================================================================================
591 DEBUG_LOCAL
int WSPAPI
NSPLookupServiceEnd( HANDLE inLookup
)
595 dlog( kDebugLevelTrace
, "%s begin (ticks=%d)\n", __ROUTINE__
, GetTickCount() );
597 dlog( kDebugLevelTrace
, "%s (lookup=%#p)\n", __ROUTINE__
, inLookup
);
600 err
= QueryRelease( (QueryRef
) inLookup
);
602 require_noerr( err
, exit
);
605 dlog( kDebugLevelTrace
, "%s end (ticks=%d)\n", __ROUTINE__
, GetTickCount() );
606 if( err
!= NO_ERROR
)
608 SetLastError( (DWORD
) err
);
609 return( SOCKET_ERROR
);
614 //===========================================================================================================================
617 // This function maps to the Winsock call WSASetService. This routine is called when the user wants to register or
618 // deregister an instance of a server with our service. For registration, the user needs to associate the server with a
619 // service class. For deregistration the service class is required along with the servicename. The inRegInfo parameter
620 // contains a WSAQUERYSET structure defining the server (such as protocol and address where it is).
621 //===========================================================================================================================
623 DEBUG_LOCAL
int WSPAPI
626 LPWSASERVICECLASSINFOW inServiceClassInfo
,
627 LPWSAQUERYSETW inRegInfo
,
628 WSAESETSERVICEOP inOperation
,
631 DEBUG_UNUSED( inProviderID
);
632 DEBUG_UNUSED( inServiceClassInfo
);
633 DEBUG_UNUSED( inRegInfo
);
634 DEBUG_UNUSED( inOperation
);
635 DEBUG_UNUSED( inFlags
);
637 dlog( kDebugLevelTrace
, "%s begin (ticks=%d)\n", __ROUTINE__
, GetTickCount() );
638 dlog( kDebugLevelTrace
, "%s\n", __ROUTINE__
);
640 // We don't allow services to be registered so always return an error.
642 dlog( kDebugLevelTrace
, "%s end (ticks=%d)\n", __ROUTINE__
, GetTickCount() );
646 //===========================================================================================================================
647 // NSPInstallServiceClass
649 // This function maps to the Winsock call WSAInstallServiceClass. This routine is used to install a service class which
650 // is used to define certain characteristics for a group of services. After a service class is registered, an actual
651 // instance of a server may be registered.
652 //===========================================================================================================================
654 DEBUG_LOCAL
int WSPAPI
NSPInstallServiceClass( LPGUID inProviderID
, LPWSASERVICECLASSINFOW inServiceClassInfo
)
656 DEBUG_UNUSED( inProviderID
);
657 DEBUG_UNUSED( inServiceClassInfo
);
659 dlog( kDebugLevelTrace
, "%s begin (ticks=%d)\n", __ROUTINE__
, GetTickCount() );
660 dlog( kDebugLevelTrace
, "%s\n", __ROUTINE__
);
662 // We don't allow service classes to be installed so always return an error.
664 dlog( kDebugLevelTrace
, "%s end (ticks=%d)\n", __ROUTINE__
, GetTickCount() );
665 return( WSA_INVALID_PARAMETER
);
668 //===========================================================================================================================
669 // NSPRemoveServiceClass
671 // This function maps to the Winsock call WSARemoveServiceClass. This routine removes a previously registered service
672 // class. This is accomplished by connecting to the namespace service and writing the GUID which defines the given
674 //===========================================================================================================================
676 DEBUG_LOCAL
int WSPAPI
NSPRemoveServiceClass( LPGUID inProviderID
, LPGUID inServiceClassID
)
678 DEBUG_UNUSED( inProviderID
);
679 DEBUG_UNUSED( inServiceClassID
);
681 dlog( kDebugLevelTrace
, "%s begin (ticks=%d)\n", __ROUTINE__
, GetTickCount() );
682 dlog( kDebugLevelTrace
, "%s\n", __ROUTINE__
);
684 // We don't allow service classes to be installed so always return an error.
686 dlog( kDebugLevelTrace
, "%s end (ticks=%d)\n", __ROUTINE__
, GetTickCount() );
687 return( WSATYPE_NOT_FOUND
);
690 //===========================================================================================================================
691 // NSPGetServiceClassInfo
693 // This function maps to the Winsock call WSAGetServiceClassInfo. This routine returns the information associated with
694 // a given service class.
695 //===========================================================================================================================
697 DEBUG_LOCAL
int WSPAPI
NSPGetServiceClassInfo( LPGUID inProviderID
, LPDWORD ioSize
, LPWSASERVICECLASSINFOW ioServiceClassInfo
)
699 DEBUG_UNUSED( inProviderID
);
700 DEBUG_UNUSED( ioSize
);
701 DEBUG_UNUSED( ioServiceClassInfo
);
703 dlog( kDebugLevelTrace
, "%s begin (ticks=%d)\n", __ROUTINE__
, GetTickCount() );
704 dlog( kDebugLevelTrace
, "%s\n", __ROUTINE__
);
706 // We don't allow service classes to be installed so always return an error.
708 dlog( kDebugLevelTrace
, "%s end (ticks=%d)\n", __ROUTINE__
, GetTickCount() );
709 return( WSATYPE_NOT_FOUND
);
716 //===========================================================================================================================
719 // Warning: Assumes the NSP lock is held.
720 //===========================================================================================================================
722 DEBUG_LOCAL OSStatus
QueryCreate( const WSAQUERYSETW
*inQuerySet
, DWORD inQuerySetFlags
, QueryRef
*outRef
)
726 char name
[ kDNSServiceMaxDomainName
];
732 check( inQuerySet
->lpszServiceInstanceName
);
735 // Convert the wchar_t name to UTF-8.
737 n
= WideCharToMultiByte( CP_UTF8
, 0, inQuerySet
->lpszServiceInstanceName
, -1, name
, sizeof( name
), NULL
, NULL
);
738 err
= translate_errno( n
> 0, (OSStatus
) GetLastError(), WSAEINVAL
);
739 require_noerr( err
, exit
);
741 // Allocate the object and append it to the list. Append immediately so releases of partial objects work.
743 obj
= (QueryRef
) calloc( 1, sizeof( *obj
) );
744 require_action( obj
, exit
, err
= WSA_NOT_ENOUGH_MEMORY
);
748 for( p
= &gQueryList
; *p
; p
= &( *p
)->next
) {} // Find the end of the list.
751 // Set up events to signal when data is ready and when cancelling.
753 obj
->dataEvent
= CreateEvent( NULL
, TRUE
, FALSE
, NULL
);
754 require_action( obj
->dataEvent
, exit
, err
= WSA_NOT_ENOUGH_MEMORY
);
756 obj
->cancelEvent
= CreateEvent( NULL
, TRUE
, FALSE
, NULL
);
757 require_action( obj
->cancelEvent
, exit
, err
= WSA_NOT_ENOUGH_MEMORY
);
761 err
= DNSServiceQueryRecord( &obj
->resolver
, 0, 0, name
, kDNSServiceType_A
, kDNSServiceClass_IN
,
762 QueryRecordCallback
, obj
);
763 require_noerr( err
, exit
);
765 // Attach the socket to the event
767 WSAEventSelect(DNSServiceRefSockFD(obj
->resolver
), obj
->dataEvent
, FD_READ
|FD_CLOSE
);
770 obj
->waitHandles
[ obj
->waitCount
++ ] = obj
->dataEvent
;
771 obj
->waitHandles
[ obj
->waitCount
++ ] = obj
->cancelEvent
;
772 check( obj
->waitCount
== sizeof_array( obj
->waitHandles
) );
774 // Copy the QuerySet so it can be returned later.
776 obj
->querySetFlags
= inQuerySetFlags
;
777 inQuerySetFlags
= ( inQuerySetFlags
& ~( LUP_RETURN_ADDR
| LUP_RETURN_BLOB
) ) | LUP_RETURN_NAME
;
778 err
= QueryCopyQuerySet( obj
, inQuerySet
, inQuerySetFlags
, &obj
->querySet
, &obj
->querySetSize
);
779 require_noerr( err
, exit
);
795 //===========================================================================================================================
798 // Warning: Assumes the NSP lock is held.
799 //===========================================================================================================================
801 DEBUG_LOCAL OSStatus
QueryRetain( QueryRef inRef
)
806 for( obj
= gQueryList
; obj
; obj
= obj
->next
)
813 require_action( obj
, exit
, err
= WSA_INVALID_HANDLE
);
822 //===========================================================================================================================
825 // Warning: Assumes the NSP lock is held.
826 //===========================================================================================================================
828 DEBUG_LOCAL OSStatus
QueryRelease( QueryRef inRef
)
834 // Find the item in the list.
836 for( p
= &gQueryList
; *p
; p
= &( *p
)->next
)
843 require_action( *p
, exit
, err
= WSA_INVALID_HANDLE
);
845 // Signal a cancel to unblock any threads waiting for results.
847 if( inRef
->cancelEvent
)
849 ok
= SetEvent( inRef
->cancelEvent
);
850 check_translated_errno( ok
, GetLastError(), WSAEINVAL
);
855 if( inRef
->resolver
)
857 DNSServiceRefDeallocate( inRef
->resolver
);
858 inRef
->resolver
= NULL
;
861 // Decrement the refCount. Fully release if it drops to 0. If still referenced, just exit.
863 if( --inRef
->refCount
!= 0 )
870 // Release resources.
872 if( inRef
->cancelEvent
)
874 ok
= CloseHandle( inRef
->cancelEvent
);
875 check_translated_errno( ok
, GetLastError(), WSAEINVAL
);
877 if( inRef
->dataEvent
)
879 ok
= CloseHandle( inRef
->dataEvent
);
880 check_translated_errno( ok
, GetLastError(), WSAEINVAL
);
882 if( inRef
->querySet
)
884 free( inRef
->querySet
);
893 //===========================================================================================================================
894 // QueryRecordCallback
895 //===========================================================================================================================
897 DEBUG_LOCAL
void CALLBACK_COMPAT
900 DNSServiceFlags inFlags
,
901 uint32_t inInterfaceIndex
,
902 DNSServiceErrorType inErrorCode
,
906 uint16_t inRDataSize
,
907 const void * inRData
,
916 DEBUG_UNUSED( inFlags
);
917 DEBUG_UNUSED( inInterfaceIndex
);
918 DEBUG_UNUSED( inTTL
);
921 obj
= (QueryRef
) inContext
;
923 require_noerr( inErrorCode
, exit
);
924 require_quiet( inFlags
& kDNSServiceFlagsAdd
, exit
);
925 require( inRRClass
== kDNSServiceClass_IN
, exit
);
926 require( inRRType
== kDNSServiceType_A
, exit
);
927 require( inRDataSize
== 4, exit
);
929 dlog( kDebugLevelTrace
, "%s (flags=0x%08X, name=%s, rrType=%d, rDataSize=%d)\n",
930 __ROUTINE__
, inFlags
, inName
, inRRType
, inRDataSize
);
932 // Copy the name if needed.
934 if( obj
->name
[ 0 ] == '\0' )
938 while( *src
!= '\0' )
943 obj
->nameSize
= (size_t)( dst
- obj
->name
);
944 check( obj
->nameSize
< sizeof( obj
->name
) );
949 memcpy( &obj
->addr
, inRData
, inRDataSize
);
950 obj
->addrValid
= true;
952 // Signal that a result is ready.
954 check( obj
->dataEvent
);
955 ok
= SetEvent( obj
->dataEvent
);
956 check_translated_errno( ok
, GetLastError(), WSAEINVAL
);
958 // Stop the resolver after the first response.
960 DNSServiceRefDeallocate( inRef
);
961 obj
->resolver
= NULL
;
971 //===========================================================================================================================
974 // Warning: Assumes the NSP lock is held.
975 //===========================================================================================================================
980 const WSAQUERYSETW
* inQuerySet
,
981 DWORD inQuerySetFlags
,
982 WSAQUERYSETW
** outQuerySet
,
990 check( outQuerySet
);
992 size
= QueryCopyQuerySetSize( inRef
, inQuerySet
, inQuerySetFlags
);
993 qs
= (WSAQUERYSETW
*) calloc( 1, size
);
994 require_action( qs
, exit
, err
= WSA_NOT_ENOUGH_MEMORY
);
996 QueryCopyQuerySetTo( inRef
, inQuerySet
, inQuerySetFlags
, qs
);
1014 //===========================================================================================================================
1015 // QueryCopyQuerySetTo
1017 // Warning: Assumes the NSP lock is held.
1018 //===========================================================================================================================
1021 QueryCopyQuerySetTo(
1023 const WSAQUERYSETW
* inQuerySet
,
1024 DWORD inQuerySetFlags
,
1025 WSAQUERYSETW
* outQuerySet
)
1036 debugSize
= QueryCopyQuerySetSize( inRef
, inQuerySet
, inQuerySetFlags
);
1039 check( inQuerySet
);
1040 check( outQuerySet
);
1042 dst
= (uint8_t *) outQuerySet
;
1044 // Copy the static portion of the results.
1046 *outQuerySet
= *inQuerySet
;
1047 dst
+= sizeof( *inQuerySet
);
1049 if( inQuerySetFlags
& LUP_RETURN_NAME
)
1051 s
= inQuerySet
->lpszServiceInstanceName
;
1054 outQuerySet
->lpszServiceInstanceName
= (LPWSTR
) dst
;
1056 while( ( *q
++ = *s
++ ) != 0 ) {}
1057 dst
= (uint8_t *) q
;
1062 outQuerySet
->lpszServiceInstanceName
= NULL
;
1065 if( inQuerySet
->lpServiceClassId
)
1067 outQuerySet
->lpServiceClassId
= (LPGUID
) dst
;
1068 *outQuerySet
->lpServiceClassId
= *inQuerySet
->lpServiceClassId
;
1069 dst
+= sizeof( *inQuerySet
->lpServiceClassId
);
1072 if( inQuerySet
->lpVersion
)
1074 outQuerySet
->lpVersion
= (LPWSAVERSION
) dst
;
1075 *outQuerySet
->lpVersion
= *inQuerySet
->lpVersion
;
1076 dst
+= sizeof( *inQuerySet
->lpVersion
);
1079 s
= inQuerySet
->lpszComment
;
1082 outQuerySet
->lpszComment
= (LPWSTR
) dst
;
1084 while( ( *q
++ = *s
++ ) != 0 ) {}
1085 dst
= (uint8_t *) q
;
1088 if( inQuerySet
->lpNSProviderId
)
1090 outQuerySet
->lpNSProviderId
= (LPGUID
) dst
;
1091 *outQuerySet
->lpNSProviderId
= *inQuerySet
->lpNSProviderId
;
1092 dst
+= sizeof( *inQuerySet
->lpNSProviderId
);
1095 s
= inQuerySet
->lpszContext
;
1098 outQuerySet
->lpszContext
= (LPWSTR
) dst
;
1100 while( ( *q
++ = *s
++ ) != 0 ) {}
1101 dst
= (uint8_t *) q
;
1104 n
= inQuerySet
->dwNumberOfProtocols
;
1107 check( inQuerySet
->lpafpProtocols
);
1109 outQuerySet
->lpafpProtocols
= (LPAFPROTOCOLS
) dst
;
1110 for( i
= 0; i
< n
; ++i
)
1112 outQuerySet
->lpafpProtocols
[ i
] = inQuerySet
->lpafpProtocols
[ i
];
1113 dst
+= sizeof( *inQuerySet
->lpafpProtocols
);
1117 s
= inQuerySet
->lpszQueryString
;
1120 outQuerySet
->lpszQueryString
= (LPWSTR
) dst
;
1122 while( ( *q
++ = *s
++ ) != 0 ) {}
1123 dst
= (uint8_t *) q
;
1126 // Copy the address(es).
1128 if( ( inQuerySetFlags
& LUP_RETURN_ADDR
) && inRef
->addrValid
)
1130 struct sockaddr_in
* addr
;
1132 outQuerySet
->dwNumberOfCsAddrs
= 1;
1133 outQuerySet
->lpcsaBuffer
= (LPCSADDR_INFO
) dst
;
1134 dst
+= sizeof( *outQuerySet
->lpcsaBuffer
);
1136 outQuerySet
->lpcsaBuffer
[ 0 ].LocalAddr
.lpSockaddr
= NULL
;
1137 outQuerySet
->lpcsaBuffer
[ 0 ].LocalAddr
.iSockaddrLength
= 0;
1139 outQuerySet
->lpcsaBuffer
[ 0 ].RemoteAddr
.lpSockaddr
= (LPSOCKADDR
) dst
;
1140 outQuerySet
->lpcsaBuffer
[ 0 ].RemoteAddr
.iSockaddrLength
= sizeof( struct sockaddr_in
);
1142 addr
= (struct sockaddr_in
*) dst
;
1143 memset( addr
, 0, sizeof( *addr
) );
1144 addr
->sin_family
= AF_INET
;
1145 memcpy( &addr
->sin_addr
, &inRef
->addr
, 4 );
1146 dst
+= sizeof( *addr
);
1148 outQuerySet
->lpcsaBuffer
[ 0 ].iSocketType
= AF_INET
; // Emulate Tcpip NSP
1149 outQuerySet
->lpcsaBuffer
[ 0 ].iProtocol
= IPPROTO_UDP
; // Emulate Tcpip NSP
1153 outQuerySet
->dwNumberOfCsAddrs
= 0;
1154 outQuerySet
->lpcsaBuffer
= NULL
;
1157 // Copy the hostent blob.
1159 if( ( inQuerySetFlags
& LUP_RETURN_BLOB
) && inRef
->addrValid
)
1162 struct hostent
* he
;
1165 outQuerySet
->lpBlob
= (LPBLOB
) dst
;
1166 dst
+= sizeof( *outQuerySet
->lpBlob
);
1169 he
= (struct hostent
*) dst
;
1170 dst
+= sizeof( *he
);
1172 he
->h_name
= (char *)( dst
- base
);
1173 memcpy( dst
, inRef
->name
, inRef
->nameSize
+ 1 );
1174 dst
+= ( inRef
->nameSize
+ 1 );
1176 he
->h_aliases
= (char **)( dst
- base
);
1177 p
= (uintptr_t *) dst
;
1179 dst
= (uint8_t *) p
;
1181 he
->h_addrtype
= AF_INET
;
1184 he
->h_addr_list
= (char **)( dst
- base
);
1185 p
= (uintptr_t *) dst
;
1186 dst
+= ( 2 * sizeof( *p
) );
1187 *p
++ = (uintptr_t)( dst
- base
);
1189 p
= (uintptr_t *) dst
;
1190 *p
++ = (uintptr_t) inRef
->addr
;
1191 dst
= (uint8_t *) p
;
1193 outQuerySet
->lpBlob
->cbSize
= (ULONG
)( dst
- base
);
1194 outQuerySet
->lpBlob
->pBlobData
= (BYTE
*) base
;
1196 dlog_query_set( kDebugLevelVerbose
, outQuerySet
);
1198 check( (size_t)( dst
- ( (uint8_t *) outQuerySet
) ) == debugSize
);
1201 //===========================================================================================================================
1202 // QueryCopyQuerySetSize
1204 // Warning: Assumes the NSP lock is held.
1205 //===========================================================================================================================
1207 DEBUG_LOCAL
size_t QueryCopyQuerySetSize( QueryRef inRef
, const WSAQUERYSETW
*inQuerySet
, DWORD inQuerySetFlags
)
1214 check( inQuerySet
);
1216 // Calculate the size of the static portion of the results.
1218 size
= sizeof( *inQuerySet
);
1220 if( inQuerySetFlags
& LUP_RETURN_NAME
)
1222 s
= inQuerySet
->lpszServiceInstanceName
;
1225 for( p
= s
; *p
; ++p
) {}
1226 size
+= (size_t)( ( ( p
- s
) + 1 ) * sizeof( *p
) );
1230 if( inQuerySet
->lpServiceClassId
)
1232 size
+= sizeof( *inQuerySet
->lpServiceClassId
);
1235 if( inQuerySet
->lpVersion
)
1237 size
+= sizeof( *inQuerySet
->lpVersion
);
1240 s
= inQuerySet
->lpszComment
;
1243 for( p
= s
; *p
; ++p
) {}
1244 size
+= (size_t)( ( ( p
- s
) + 1 ) * sizeof( *p
) );
1247 if( inQuerySet
->lpNSProviderId
)
1249 size
+= sizeof( *inQuerySet
->lpNSProviderId
);
1252 s
= inQuerySet
->lpszContext
;
1255 for( p
= s
; *p
; ++p
) {}
1256 size
+= (size_t)( ( ( p
- s
) + 1 ) * sizeof( *p
) );
1259 size
+= ( inQuerySet
->dwNumberOfProtocols
* sizeof( *inQuerySet
->lpafpProtocols
) );
1261 s
= inQuerySet
->lpszQueryString
;
1264 for( p
= s
; *p
; ++p
) {}
1265 size
+= (size_t)( ( ( p
- s
) + 1 ) * sizeof( *p
) );
1268 // Calculate the size of the address(es).
1270 if( ( inQuerySetFlags
& LUP_RETURN_ADDR
) && inRef
->addrValid
)
1272 size
+= sizeof( *inQuerySet
->lpcsaBuffer
);
1273 size
+= sizeof( struct sockaddr_in
);
1276 // Calculate the size of the hostent blob.
1278 if( ( inQuerySetFlags
& LUP_RETURN_BLOB
) && inRef
->addrValid
)
1280 size
+= sizeof( *inQuerySet
->lpBlob
); // Blob ptr/size structure
1281 size
+= sizeof( struct hostent
); // Old-style hostent structure
1282 size
+= ( inRef
->nameSize
+ 1 ); // Name and null terminator
1283 size
+= 4; // Alias list terminator (0 offset)
1284 size
+= 4; // Offset to address.
1285 size
+= 4; // Address list terminator (0 offset)
1286 size
+= 4; // IPv4 address
1296 //===========================================================================================================================
1297 // DebugDumpQuerySet
1298 //===========================================================================================================================
1300 #define DebugSocketFamilyToString( FAM ) ( ( FAM ) == AF_INET ) ? "AF_INET" : \
1301 ( ( FAM ) == AF_INET6 ) ? "AF_INET6" : ""
1303 #define DebugSocketProtocolToString( PROTO ) ( ( PROTO ) == IPPROTO_UDP ) ? "IPPROTO_UDP" : \
1304 ( ( PROTO ) == IPPROTO_TCP ) ? "IPPROTO_TCP" : ""
1306 #define DebugNameSpaceToString( NS ) ( ( NS ) == NS_DNS ) ? "NS_DNS" : ( ( NS ) == NS_ALL ) ? "NS_ALL" : ""
1308 void DebugDumpQuerySet( DebugLevel inLevel
, const WSAQUERYSETW
*inQuerySet
)
1312 check( inQuerySet
);
1314 // Fixed portion of the QuerySet.
1316 dlog( inLevel
, "QuerySet:\n" );
1317 dlog( inLevel
, " dwSize: %d (expected %d)\n", inQuerySet
->dwSize
, sizeof( *inQuerySet
) );
1318 if( inQuerySet
->lpszServiceInstanceName
)
1320 dlog( inLevel
, " lpszServiceInstanceName: %S\n", inQuerySet
->lpszServiceInstanceName
);
1324 dlog( inLevel
, " lpszServiceInstanceName: <null>\n" );
1326 if( inQuerySet
->lpServiceClassId
)
1328 dlog( inLevel
, " lpServiceClassId: %U\n", inQuerySet
->lpServiceClassId
);
1332 dlog( inLevel
, " lpServiceClassId: <null>\n" );
1334 if( inQuerySet
->lpVersion
)
1336 dlog( inLevel
, " lpVersion:\n" );
1337 dlog( inLevel
, " dwVersion: %d\n", inQuerySet
->lpVersion
->dwVersion
);
1338 dlog( inLevel
, " dwVersion: %d\n", inQuerySet
->lpVersion
->ecHow
);
1342 dlog( inLevel
, " lpVersion: <null>\n" );
1344 if( inQuerySet
->lpszComment
)
1346 dlog( inLevel
, " lpszComment: %S\n", inQuerySet
->lpszComment
);
1350 dlog( inLevel
, " lpszComment: <null>\n" );
1352 dlog( inLevel
, " dwNameSpace: %d %s\n", inQuerySet
->dwNameSpace
,
1353 DebugNameSpaceToString( inQuerySet
->dwNameSpace
) );
1354 if( inQuerySet
->lpNSProviderId
)
1356 dlog( inLevel
, " lpNSProviderId: %U\n", inQuerySet
->lpNSProviderId
);
1360 dlog( inLevel
, " lpNSProviderId: <null>\n" );
1362 if( inQuerySet
->lpszContext
)
1364 dlog( inLevel
, " lpszContext: %S\n", inQuerySet
->lpszContext
);
1368 dlog( inLevel
, " lpszContext: <null>\n" );
1370 dlog( inLevel
, " dwNumberOfProtocols: %d\n", inQuerySet
->dwNumberOfProtocols
);
1371 dlog( inLevel
, " lpafpProtocols: %s\n", inQuerySet
->lpafpProtocols
? "" : "<null>" );
1372 for( i
= 0; i
< inQuerySet
->dwNumberOfProtocols
; ++i
)
1376 dlog( inLevel
, "\n" );
1378 dlog( inLevel
, " iAddressFamily: %d %s\n", inQuerySet
->lpafpProtocols
[ i
].iAddressFamily
,
1379 DebugSocketFamilyToString( inQuerySet
->lpafpProtocols
[ i
].iAddressFamily
) );
1380 dlog( inLevel
, " iProtocol: %d %s\n", inQuerySet
->lpafpProtocols
[ i
].iProtocol
,
1381 DebugSocketProtocolToString( inQuerySet
->lpafpProtocols
[ i
].iProtocol
) );
1383 if( inQuerySet
->lpszQueryString
)
1385 dlog( inLevel
, " lpszQueryString: %S\n", inQuerySet
->lpszQueryString
);
1389 dlog( inLevel
, " lpszQueryString: <null>\n" );
1391 dlog( inLevel
, " dwNumberOfCsAddrs: %d\n", inQuerySet
->dwNumberOfCsAddrs
);
1392 dlog( inLevel
, " lpcsaBuffer: %s\n", inQuerySet
->lpcsaBuffer
? "" : "<null>" );
1393 for( i
= 0; i
< inQuerySet
->dwNumberOfCsAddrs
; ++i
)
1397 dlog( inLevel
, "\n" );
1399 if( inQuerySet
->lpcsaBuffer
[ i
].LocalAddr
.lpSockaddr
&&
1400 ( inQuerySet
->lpcsaBuffer
[ i
].LocalAddr
.iSockaddrLength
> 0 ) )
1402 dlog( inLevel
, " LocalAddr: %##a\n",
1403 inQuerySet
->lpcsaBuffer
[ i
].LocalAddr
.lpSockaddr
);
1407 dlog( inLevel
, " LocalAddr: <null/empty>\n" );
1409 if( inQuerySet
->lpcsaBuffer
[ i
].RemoteAddr
.lpSockaddr
&&
1410 ( inQuerySet
->lpcsaBuffer
[ i
].RemoteAddr
.iSockaddrLength
> 0 ) )
1412 dlog( inLevel
, " RemoteAddr: %##a\n",
1413 inQuerySet
->lpcsaBuffer
[ i
].RemoteAddr
.lpSockaddr
);
1417 dlog( inLevel
, " RemoteAddr: <null/empty>\n" );
1419 dlog( inLevel
, " iSocketType: %d\n", inQuerySet
->lpcsaBuffer
[ i
].iSocketType
);
1420 dlog( inLevel
, " iProtocol: %d\n", inQuerySet
->lpcsaBuffer
[ i
].iProtocol
);
1422 dlog( inLevel
, " dwOutputFlags: %d\n", inQuerySet
->dwOutputFlags
);
1424 // Blob portion of the QuerySet.
1426 if( inQuerySet
->lpBlob
)
1428 dlog( inLevel
, " lpBlob:\n" );
1429 dlog( inLevel
, " cbSize: %ld\n", inQuerySet
->lpBlob
->cbSize
);
1430 dlog( inLevel
, " pBlobData: %#p\n", inQuerySet
->lpBlob
->pBlobData
);
1431 dloghex( inLevel
, 12, NULL
, 0, 0, NULL
, 0,
1432 inQuerySet
->lpBlob
->pBlobData
, inQuerySet
->lpBlob
->pBlobData
, inQuerySet
->lpBlob
->cbSize
,
1433 kDebugFlagsNone
, NULL
, 0 );
1437 dlog( inLevel
, " lpBlob: <null>\n" );