Home | History | Annotate | Download | only in DLLX
      1 // DNSSD.cpp : Implementation of CDNSSD
      2 
      3 #include "stdafx.h"
      4 #include "DNSSD.h"
      5 #include "DNSSDService.h"
      6 #include "TXTRecord.h"
      7 #include <dns_sd.h>
      8 #include <CommonServices.h>
      9 #include <DebugServices.h>
     10 #include "StringServices.h"
     11 
     12 
     13 // CDNSSD
     14 
     15 STDMETHODIMP CDNSSD::Browse(DNSSDFlags flags, ULONG ifIndex, BSTR regtype, BSTR domain, IBrowseListener* listener, IDNSSDService** browser )
     16 {
     17 	CComObject<CDNSSDService>	*	object		= NULL;
     18 	std::string						regtypeUTF8;
     19 	std::string						domainUTF8;
     20 	DNSServiceRef					sref		= NULL;
     21 	DNSServiceErrorType				err			= 0;
     22 	HRESULT							hr			= 0;
     23 	BOOL							ok;
     24 
     25 	// Initialize
     26 	*browser = NULL;
     27 
     28 	// Convert BSTR params to utf8
     29 	ok = BSTRToUTF8( regtype, regtypeUTF8 );
     30 	require_action( ok, exit, err = kDNSServiceErr_BadParam );
     31 	ok = BSTRToUTF8( domain, domainUTF8 );
     32 	require_action( ok, exit, err = kDNSServiceErr_BadParam );
     33 
     34 	try
     35 	{
     36 		object = new CComObject<CDNSSDService>();
     37 	}
     38 	catch ( ... )
     39 	{
     40 		object = NULL;
     41 	}
     42 
     43 	require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
     44 	hr = object->FinalConstruct();
     45 	require_action( hr == S_OK, exit, err = kDNSServiceErr_Unknown );
     46 	object->AddRef();
     47 
     48 	err = DNSServiceBrowse( &sref, flags, ifIndex, regtypeUTF8.c_str(), domainUTF8.c_str(), ( DNSServiceBrowseReply ) &BrowseReply, object );
     49 	require_noerr( err, exit );
     50 
     51 	object->SetServiceRef( sref );
     52 	object->SetListener( listener );
     53 
     54 	err = object->Run();
     55 	require_noerr( err, exit );
     56 
     57 	*browser = object;
     58 
     59 exit:
     60 
     61 	if ( err && object )
     62 	{
     63 		object->Release();
     64 	}
     65 
     66 	return err;
     67 }
     68 
     69 
     70 STDMETHODIMP CDNSSD::Resolve(DNSSDFlags flags, ULONG ifIndex, BSTR serviceName, BSTR regType, BSTR domain, IResolveListener* listener, IDNSSDService** service)
     71 {
     72 	CComObject<CDNSSDService>	*	object			= NULL;
     73 	std::string						serviceNameUTF8;
     74 	std::string						regTypeUTF8;
     75 	std::string						domainUTF8;
     76 	DNSServiceRef					sref			= NULL;
     77 	DNSServiceErrorType				err				= 0;
     78 	HRESULT							hr				= 0;
     79 	BOOL							ok;
     80 
     81 	// Initialize
     82 	*service = NULL;
     83 
     84 	// Convert BSTR params to utf8
     85 	ok = BSTRToUTF8( serviceName, serviceNameUTF8 );
     86 	require_action( ok, exit, err = kDNSServiceErr_BadParam );
     87 	ok = BSTRToUTF8( regType, regTypeUTF8 );
     88 	require_action( ok, exit, err = kDNSServiceErr_BadParam );
     89 	ok = BSTRToUTF8( domain, domainUTF8 );
     90 	require_action( ok, exit, err = kDNSServiceErr_BadParam );
     91 
     92 	try
     93 	{
     94 		object = new CComObject<CDNSSDService>();
     95 	}
     96 	catch ( ... )
     97 	{
     98 		object = NULL;
     99 	}
    100 
    101 	require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
    102 	hr = object->FinalConstruct();
    103 	require_action( hr == S_OK, exit, err = kDNSServiceErr_Unknown );
    104 	object->AddRef();
    105 
    106 	err = DNSServiceResolve( &sref, flags, ifIndex, serviceNameUTF8.c_str(), regTypeUTF8.c_str(), domainUTF8.c_str(), ( DNSServiceResolveReply ) &ResolveReply, object );
    107 	require_noerr( err, exit );
    108 
    109 	object->SetServiceRef( sref );
    110 	object->SetListener( listener );
    111 
    112 	err = object->Run();
    113 	require_noerr( err, exit );
    114 
    115 	*service = object;
    116 
    117 exit:
    118 
    119 	if ( err && object )
    120 	{
    121 		object->Release();
    122 	}
    123 
    124 	return err;
    125 }
    126 
    127 
    128 STDMETHODIMP CDNSSD::EnumerateDomains(DNSSDFlags flags, ULONG ifIndex, IDomainListener *listener, IDNSSDService **service)
    129 {
    130 	CComObject<CDNSSDService>	*	object			= NULL;
    131 	DNSServiceRef					sref			= NULL;
    132 	DNSServiceErrorType				err				= 0;
    133 	HRESULT							hr				= 0;
    134 
    135 	// Initialize
    136 	*service = NULL;
    137 
    138 	try
    139 	{
    140 		object = new CComObject<CDNSSDService>();
    141 	}
    142 	catch ( ... )
    143 	{
    144 		object = NULL;
    145 	}
    146 
    147 	require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
    148 	hr = object->FinalConstruct();
    149 	require_action( hr == S_OK, exit, err = kDNSServiceErr_Unknown );
    150 	object->AddRef();
    151 
    152 	err = DNSServiceEnumerateDomains( &sref, flags, ifIndex, ( DNSServiceDomainEnumReply ) &DomainEnumReply, object );
    153 	require_noerr( err, exit );
    154 
    155 	object->SetServiceRef( sref );
    156 	object->SetListener( listener );
    157 
    158 	err = object->Run();
    159 	require_noerr( err, exit );
    160 
    161 	*service = object;
    162 
    163 exit:
    164 
    165 	if ( err && object )
    166 	{
    167 		object->Release();
    168 	}
    169 
    170 	return err;
    171 }
    172 
    173 
    174 STDMETHODIMP CDNSSD::Register(DNSSDFlags flags, ULONG ifIndex, BSTR serviceName, BSTR regType, BSTR domain, BSTR host, USHORT port, ITXTRecord *record, IRegisterListener *listener, IDNSSDService **service)
    175 {
    176 	CComObject<CDNSSDService>	*	object			= NULL;
    177 	std::string						serviceNameUTF8;
    178 	std::string						regTypeUTF8;
    179 	std::string						domainUTF8;
    180 	std::string						hostUTF8;
    181 	const void					*	txtRecord		= NULL;
    182 	uint16_t						txtLen			= 0;
    183 	DNSServiceRef					sref			= NULL;
    184 	DNSServiceErrorType				err				= 0;
    185 	HRESULT							hr				= 0;
    186 	BOOL							ok;
    187 
    188 	// Initialize
    189 	*service = NULL;
    190 
    191 	// Convert BSTR params to utf8
    192 	ok = BSTRToUTF8( serviceName, serviceNameUTF8 );
    193 	require_action( ok, exit, err = kDNSServiceErr_BadParam );
    194 	ok = BSTRToUTF8( regType, regTypeUTF8 );
    195 	require_action( ok, exit, err = kDNSServiceErr_BadParam );
    196 	ok = BSTRToUTF8( domain, domainUTF8 );
    197 	require_action( ok, exit, err = kDNSServiceErr_BadParam );
    198 	ok = BSTRToUTF8( host, hostUTF8 );
    199 	require_action( ok, exit, err = kDNSServiceErr_BadParam );
    200 
    201 	try
    202 	{
    203 		object = new CComObject<CDNSSDService>();
    204 	}
    205 	catch ( ... )
    206 	{
    207 		object = NULL;
    208 	}
    209 
    210 	require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
    211 	hr = object->FinalConstruct();
    212 	require_action( hr == S_OK, exit, err = kDNSServiceErr_Unknown );
    213 	object->AddRef();
    214 
    215 	if ( record )
    216 	{
    217 		CComObject< CTXTRecord > * realTXTRecord;
    218 
    219 		realTXTRecord = ( CComObject< CTXTRecord >* ) record;
    220 
    221 		txtRecord	= realTXTRecord->GetBytes();
    222 		txtLen		= realTXTRecord->GetLen();
    223 	}
    224 
    225 	err = DNSServiceRegister( &sref, flags, ifIndex, serviceNameUTF8.c_str(), regTypeUTF8.c_str(), domainUTF8.c_str(), hostUTF8.c_str(), port, txtLen, txtRecord, ( DNSServiceRegisterReply ) &RegisterReply, object );
    226 	require_noerr( err, exit );
    227 
    228 	object->SetServiceRef( sref );
    229 	object->SetListener( listener );
    230 
    231 	err = object->Run();
    232 	require_noerr( err, exit );
    233 
    234 	*service = object;
    235 
    236 exit:
    237 
    238 	if ( err && object )
    239 	{
    240 		object->Release();
    241 	}
    242 
    243 	return err;
    244 }
    245 
    246 
    247 STDMETHODIMP CDNSSD::QueryRecord(DNSSDFlags flags, ULONG ifIndex, BSTR fullname, DNSSDRRType rrtype, DNSSDRRClass rrclass, IQueryRecordListener *listener, IDNSSDService **service)
    248 {
    249 	CComObject<CDNSSDService>	*	object			= NULL;
    250 	DNSServiceRef					sref			= NULL;
    251 	std::string						fullNameUTF8;
    252 	DNSServiceErrorType				err				= 0;
    253 	HRESULT							hr				= 0;
    254 	BOOL							ok;
    255 
    256 	// Initialize
    257 	*service = NULL;
    258 
    259 	// Convert BSTR params to utf8
    260 	ok = BSTRToUTF8( fullname, fullNameUTF8 );
    261 	require_action( ok, exit, err = kDNSServiceErr_BadParam );
    262 
    263 	try
    264 	{
    265 		object = new CComObject<CDNSSDService>();
    266 	}
    267 	catch ( ... )
    268 	{
    269 		object = NULL;
    270 	}
    271 
    272 	require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
    273 	hr = object->FinalConstruct();
    274 	require_action( hr == S_OK, exit, err = kDNSServiceErr_Unknown );
    275 	object->AddRef();
    276 
    277 	err = DNSServiceQueryRecord( &sref, flags, ifIndex, fullNameUTF8.c_str(), ( uint16_t ) rrtype, ( uint16_t ) rrclass, ( DNSServiceQueryRecordReply ) &QueryRecordReply, object );
    278 	require_noerr( err, exit );
    279 
    280 	object->SetServiceRef( sref );
    281 	object->SetListener( listener );
    282 
    283 	err = object->Run();
    284 	require_noerr( err, exit );
    285 
    286 	*service = object;
    287 
    288 exit:
    289 
    290 	if ( err && object )
    291 	{
    292 		object->Release();
    293 	}
    294 
    295 	return err;
    296 }
    297 
    298 
    299 STDMETHODIMP CDNSSD::GetAddrInfo(DNSSDFlags flags, ULONG ifIndex, DNSSDAddressFamily addressFamily, BSTR hostName, IGetAddrInfoListener *listener, IDNSSDService **service)
    300 {
    301 	CComObject<CDNSSDService>	*	object			= NULL;
    302 	DNSServiceRef					sref			= NULL;
    303 	std::string						hostNameUTF8;
    304 	DNSServiceErrorType				err				= 0;
    305 	HRESULT							hr				= 0;
    306 	BOOL							ok;
    307 
    308 	// Initialize
    309 	*service = NULL;
    310 
    311 	// Convert BSTR params to utf8
    312 	ok = BSTRToUTF8( hostName, hostNameUTF8 );
    313 	require_action( ok, exit, err = kDNSServiceErr_BadParam );
    314 
    315 	try
    316 	{
    317 		object = new CComObject<CDNSSDService>();
    318 	}
    319 	catch ( ... )
    320 	{
    321 		object = NULL;
    322 	}
    323 
    324 	require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
    325 	hr = object->FinalConstruct();
    326 	require_action( hr == S_OK, exit, err = kDNSServiceErr_Unknown );
    327 	object->AddRef();
    328 
    329 	err = DNSServiceGetAddrInfo( &sref, flags, ifIndex, addressFamily, hostNameUTF8.c_str(), ( DNSServiceGetAddrInfoReply ) &GetAddrInfoReply, object );
    330 	require_noerr( err, exit );
    331 
    332 	object->SetServiceRef( sref );
    333 	object->SetListener( listener );
    334 
    335 	err = object->Run();
    336 	require_noerr( err, exit );
    337 
    338 	*service = object;
    339 
    340 exit:
    341 
    342 	if ( err && object )
    343 	{
    344 		object->Release();
    345 	}
    346 
    347 	return err;
    348 }
    349 
    350 
    351 STDMETHODIMP CDNSSD::CreateConnection(IDNSSDService **service)
    352 {
    353 	CComObject<CDNSSDService>	*	object	= NULL;
    354 	DNSServiceRef					sref	= NULL;
    355 	DNSServiceErrorType				err		= 0;
    356 	HRESULT							hr		= 0;
    357 
    358 	// Initialize
    359 	*service = NULL;
    360 
    361 	try
    362 	{
    363 		object = new CComObject<CDNSSDService>();
    364 	}
    365 	catch ( ... )
    366 	{
    367 		object = NULL;
    368 	}
    369 
    370 	require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
    371 	hr = object->FinalConstruct();
    372 	require_action( hr == S_OK, exit, err = kDNSServiceErr_Unknown );
    373 	object->AddRef();
    374 
    375 	err = DNSServiceCreateConnection( &sref );
    376 	require_noerr( err, exit );
    377 
    378 	object->SetServiceRef( sref );
    379 
    380 	*service = object;
    381 
    382 exit:
    383 
    384 	if ( err && object )
    385 	{
    386 		object->Release();
    387 	}
    388 
    389 	return err;
    390 }
    391 
    392 
    393 STDMETHODIMP CDNSSD::NATPortMappingCreate(DNSSDFlags flags, ULONG ifIndex, DNSSDAddressFamily addressFamily, DNSSDProtocol protocol, USHORT internalPort, USHORT externalPort, ULONG ttl, INATPortMappingListener *listener, IDNSSDService **service)
    394 {
    395 	CComObject<CDNSSDService>	*	object			= NULL;
    396 	DNSServiceRef					sref			= NULL;
    397 	DNSServiceProtocol				prot			= 0;
    398 	DNSServiceErrorType				err				= 0;
    399 	HRESULT							hr				= 0;
    400 
    401 	// Initialize
    402 	*service = NULL;
    403 
    404 	try
    405 	{
    406 		object = new CComObject<CDNSSDService>();
    407 	}
    408 	catch ( ... )
    409 	{
    410 		object = NULL;
    411 	}
    412 
    413 	require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
    414 	hr = object->FinalConstruct();
    415 	require_action( hr == S_OK, exit, err = kDNSServiceErr_Unknown );
    416 	object->AddRef();
    417 
    418 	prot = ( addressFamily | protocol );
    419 
    420 	err = DNSServiceNATPortMappingCreate( &sref, flags, ifIndex, prot, internalPort, externalPort, ttl, ( DNSServiceNATPortMappingReply ) &NATPortMappingReply, object );
    421 	require_noerr( err, exit );
    422 
    423 	object->SetServiceRef( sref );
    424 	object->SetListener( listener );
    425 
    426 	err = object->Run();
    427 	require_noerr( err, exit );
    428 
    429 	*service = object;
    430 
    431 exit:
    432 
    433 	if ( err && object )
    434 	{
    435 		object->Release();
    436 	}
    437 
    438 	return err;
    439 }
    440 
    441 
    442 STDMETHODIMP CDNSSD::GetProperty(BSTR prop, VARIANT * value )
    443 {
    444 	std::string			propUTF8;
    445 	std::vector< BYTE >	byteArray;
    446 	SAFEARRAY		*	psa			= NULL;
    447 	BYTE			*	pData		= NULL;
    448 	uint32_t			elems		= 0;
    449 	DNSServiceErrorType	err			= 0;
    450 	BOOL				ok = TRUE;
    451 
    452 	// Convert BSTR params to utf8
    453 	ok = BSTRToUTF8( prop, propUTF8 );
    454 	require_action( ok, exit, err = kDNSServiceErr_BadParam );
    455 
    456 	// Setup the byte array
    457 	require_action( V_VT( value ) == ( VT_ARRAY|VT_UI1 ), exit, err = kDNSServiceErr_Unknown );
    458 	psa = V_ARRAY( value );
    459 	require_action( psa, exit, err = kDNSServiceErr_Unknown );
    460 	require_action( SafeArrayGetDim( psa ) == 1, exit, err = kDNSServiceErr_Unknown );
    461 	byteArray.reserve( psa->rgsabound[0].cElements );
    462 	byteArray.assign( byteArray.capacity(), 0 );
    463 	elems = ( uint32_t ) byteArray.capacity();
    464 
    465 	// Call the function and package the return value in the Variant
    466 	err = DNSServiceGetProperty( propUTF8.c_str(), &byteArray[ 0 ], &elems );
    467 	require_noerr( err, exit );
    468 	ok = ByteArrayToVariant( &byteArray[ 0 ], elems, value );
    469 	require_action( ok, exit, err = kDNSSDError_Unknown );
    470 
    471 exit:
    472 
    473 	if ( psa )
    474 	{
    475 		SafeArrayUnaccessData( psa );
    476 		psa = NULL;
    477 	}
    478 
    479 	return err;
    480 }
    481 
    482 
    483 void DNSSD_API
    484 CDNSSD::DomainEnumReply
    485     (
    486     DNSServiceRef                       sdRef,
    487     DNSServiceFlags                     flags,
    488     uint32_t                            ifIndex,
    489     DNSServiceErrorType                 errorCode,
    490     const char                          *replyDomainUTF8,
    491     void                                *context
    492     )
    493 {
    494 	CComObject<CDNSSDService> * service;
    495 	int err;
    496 
    497 	service = ( CComObject< CDNSSDService>* ) context;
    498 	require_action( service, exit, err = kDNSServiceErr_Unknown );
    499 
    500 	if ( !service->Stopped() )
    501 	{
    502 		IDomainListener	* listener;
    503 
    504 		listener = ( IDomainListener* ) service->GetListener();
    505 		require_action( listener, exit, err = kDNSServiceErr_Unknown );
    506 
    507 		if ( !errorCode )
    508 		{
    509 			CComBSTR replyDomain;
    510 
    511 			UTF8ToBSTR( replyDomainUTF8, replyDomain );
    512 
    513 			if ( flags & kDNSServiceFlagsAdd )
    514 			{
    515 				listener->DomainFound( service, ( DNSSDFlags ) flags, ifIndex, replyDomain );
    516 			}
    517 			else
    518 			{
    519 				listener->DomainLost( service, ( DNSSDFlags ) flags, ifIndex, replyDomain );
    520 			}
    521 		}
    522 		else
    523 		{
    524 			listener->EnumDomainsFailed( service, ( DNSSDError ) errorCode );
    525 		}
    526 	}
    527 
    528 exit:
    529 
    530 	return;
    531 }
    532 
    533 
    534 void DNSSD_API
    535 CDNSSD::BrowseReply
    536 		(
    537 		DNSServiceRef                       sdRef,
    538 		DNSServiceFlags                     flags,
    539 		uint32_t                            ifIndex,
    540 		DNSServiceErrorType                 errorCode,
    541 		const char                          *serviceNameUTF8,
    542 		const char                          *regTypeUTF8,
    543 		const char                          *replyDomainUTF8,
    544 		void                                *context
    545 		)
    546 {
    547 	CComObject<CDNSSDService> * service;
    548 	int err;
    549 
    550 	service = ( CComObject< CDNSSDService>* ) context;
    551 	require_action( service, exit, err = kDNSServiceErr_Unknown );
    552 
    553 	if ( !service->Stopped() )
    554 	{
    555 		IBrowseListener	* listener;
    556 
    557 		listener = ( IBrowseListener* ) service->GetListener();
    558 		require_action( listener, exit, err = kDNSServiceErr_Unknown );
    559 
    560 		if ( !errorCode )
    561 		{
    562 			CComBSTR	serviceName;
    563 			CComBSTR	regType;
    564 			CComBSTR	replyDomain;
    565 
    566 			UTF8ToBSTR( serviceNameUTF8, serviceName );
    567 			UTF8ToBSTR( regTypeUTF8, regType );
    568 			UTF8ToBSTR( replyDomainUTF8, replyDomain );
    569 
    570 			if ( flags & kDNSServiceFlagsAdd )
    571 			{
    572 				listener->ServiceFound( service, ( DNSSDFlags ) flags, ifIndex, serviceName, regType, replyDomain );
    573 			}
    574 			else
    575 			{
    576 				listener->ServiceLost( service, ( DNSSDFlags ) flags, ifIndex, serviceName, regType, replyDomain );
    577 			}
    578 		}
    579 		else
    580 		{
    581 			listener->BrowseFailed( service, ( DNSSDError ) errorCode );
    582 		}
    583 	}
    584 
    585 exit:
    586 
    587 	return;
    588 }
    589 
    590 
    591 void DNSSD_API
    592 CDNSSD::ResolveReply
    593 		(
    594 		DNSServiceRef                       sdRef,
    595 		DNSServiceFlags                     flags,
    596 		uint32_t                            ifIndex,
    597 		DNSServiceErrorType                 errorCode,
    598 		const char                          *fullNameUTF8,
    599 		const char                          *hostNameUTF8,
    600 		uint16_t                            port,
    601 		uint16_t                            txtLen,
    602 		const unsigned char                 *txtRecord,
    603 		void                                *context
    604 		)
    605 {
    606 	CComObject<CDNSSDService> * service;
    607 	int err;
    608 
    609 	service = ( CComObject< CDNSSDService>* ) context;
    610 	require_action( service, exit, err = kDNSServiceErr_Unknown );
    611 
    612 	if ( !service->Stopped() )
    613 	{
    614 		IResolveListener * listener;
    615 
    616 		listener = ( IResolveListener* ) service->GetListener();
    617 		require_action( listener, exit, err = kDNSServiceErr_Unknown );
    618 
    619 		if ( !errorCode )
    620 		{
    621 			CComBSTR					fullName;
    622 			CComBSTR					hostName;
    623 			CComBSTR					regType;
    624 			CComBSTR					replyDomain;
    625 			CComObject< CTXTRecord >*	record;
    626 			BOOL						ok;
    627 
    628 			ok = UTF8ToBSTR( fullNameUTF8, fullName );
    629 			require_action( ok, exit, err = kDNSServiceErr_Unknown );
    630 			ok = UTF8ToBSTR( hostNameUTF8, hostName );
    631 			require_action( ok, exit, err = kDNSServiceErr_Unknown );
    632 
    633 			try
    634 			{
    635 				record = new CComObject<CTXTRecord>();
    636 			}
    637 			catch ( ... )
    638 			{
    639 				record = NULL;
    640 			}
    641 
    642 			require_action( record, exit, err = kDNSServiceErr_NoMemory );
    643 			record->AddRef();
    644 
    645 			char buf[ 64 ];
    646 			sprintf( buf, "txtLen = %d", txtLen );
    647 			OutputDebugStringA( buf );
    648 
    649 			if ( txtLen > 0 )
    650 			{
    651 				record->SetBytes( txtRecord, txtLen );
    652 			}
    653 
    654 			listener->ServiceResolved( service, ( DNSSDFlags ) flags, ifIndex, fullName, hostName, port, record );
    655 		}
    656 		else
    657 		{
    658 			listener->ResolveFailed( service, ( DNSSDError ) errorCode );
    659 		}
    660 	}
    661 
    662 exit:
    663 
    664 	return;
    665 }
    666 
    667 
    668 void DNSSD_API
    669 CDNSSD::RegisterReply
    670 		(
    671 		DNSServiceRef                       sdRef,
    672 		DNSServiceFlags                     flags,
    673 		DNSServiceErrorType                 errorCode,
    674 		const char                          *serviceNameUTF8,
    675 		const char                          *regTypeUTF8,
    676 		const char                          *domainUTF8,
    677 		void                                *context
    678 		)
    679 {
    680 	CComObject<CDNSSDService> * service;
    681 	int err;
    682 
    683 	service = ( CComObject< CDNSSDService>* ) context;
    684 	require_action( service, exit, err = kDNSServiceErr_Unknown );
    685 
    686 	if ( !service->Stopped() )
    687 	{
    688 		IRegisterListener * listener;
    689 
    690 		listener = ( IRegisterListener* ) service->GetListener();
    691 		require_action( listener, exit, err = kDNSServiceErr_Unknown );
    692 
    693 		if ( !errorCode )
    694 		{
    695 			CComBSTR					serviceName;
    696 			CComBSTR					regType;
    697 			CComBSTR					domain;
    698 			BOOL						ok;
    699 
    700 			ok = UTF8ToBSTR( serviceNameUTF8, serviceName );
    701 			require_action( ok, exit, err = kDNSServiceErr_Unknown );
    702 			ok = UTF8ToBSTR( regTypeUTF8, regType );
    703 			require_action( ok, exit, err = kDNSServiceErr_Unknown );
    704 			ok = UTF8ToBSTR( domainUTF8, domain );
    705 			require_action( ok, exit, err = kDNSServiceErr_Unknown );
    706 
    707 			listener->ServiceRegistered( service, ( DNSSDFlags ) flags, serviceName, regType, domain );
    708 		}
    709 		else
    710 		{
    711 			listener->ServiceRegisterFailed( service, ( DNSSDError ) errorCode );
    712 		}
    713 	}
    714 
    715 exit:
    716 
    717 	return;
    718 }
    719 
    720 
    721 void DNSSD_API
    722 CDNSSD::QueryRecordReply
    723 		(
    724 		DNSServiceRef                       sdRef,
    725 		DNSServiceFlags                     flags,
    726 		uint32_t                            ifIndex,
    727 		DNSServiceErrorType                 errorCode,
    728 		const char                          *fullNameUTF8,
    729 		uint16_t                            rrtype,
    730 		uint16_t                            rrclass,
    731 		uint16_t                            rdlen,
    732 		const void                          *rdata,
    733 		uint32_t                            ttl,
    734 		void                                *context
    735 		)
    736 {
    737 	CComObject<CDNSSDService> * service;
    738 	int err;
    739 
    740 	service = ( CComObject< CDNSSDService>* ) context;
    741 	require_action( service, exit, err = kDNSServiceErr_Unknown );
    742 
    743 	if ( !service->Stopped() )
    744 	{
    745 		IQueryRecordListener * listener;
    746 
    747 		listener = ( IQueryRecordListener* ) service->GetListener();
    748 		require_action( listener, exit, err = kDNSServiceErr_Unknown );
    749 
    750 		if ( !errorCode )
    751 		{
    752 			CComBSTR	fullName;
    753 			VARIANT		var;
    754 			BOOL		ok;
    755 
    756 			ok = UTF8ToBSTR( fullNameUTF8, fullName );
    757 			require_action( ok, exit, err = kDNSServiceErr_Unknown );
    758 			ok = ByteArrayToVariant( rdata, rdlen, &var );
    759 			require_action( ok, exit, err = kDNSServiceErr_Unknown );
    760 
    761 			listener->QueryRecordAnswered( service, ( DNSSDFlags ) flags, ifIndex, fullName, ( DNSSDRRType ) rrtype, ( DNSSDRRClass ) rrclass, var, ttl );
    762 		}
    763 		else
    764 		{
    765 			listener->QueryRecordFailed( service, ( DNSSDError ) errorCode );
    766 		}
    767 	}
    768 
    769 exit:
    770 
    771 	return;
    772 }
    773 
    774 
    775 void DNSSD_API
    776 CDNSSD::GetAddrInfoReply
    777 		(
    778 		DNSServiceRef                    sdRef,
    779 		DNSServiceFlags                  flags,
    780 		uint32_t                         ifIndex,
    781 		DNSServiceErrorType              errorCode,
    782 		const char                       *hostNameUTF8,
    783 		const struct sockaddr            *rawAddress,
    784 		uint32_t                         ttl,
    785 		void                             *context
    786 		)
    787 {
    788 	CComObject<CDNSSDService> * service;
    789 	int err;
    790 
    791 	service = ( CComObject< CDNSSDService>* ) context;
    792 	require_action( service, exit, err = kDNSServiceErr_Unknown );
    793 
    794 	if ( !service->Stopped() )
    795 	{
    796 		IGetAddrInfoListener * listener;
    797 
    798 		listener = ( IGetAddrInfoListener* ) service->GetListener();
    799 		require_action( listener, exit, err = kDNSServiceErr_Unknown );
    800 
    801 		if ( !errorCode )
    802 		{
    803 			CComBSTR			hostName;
    804 			DWORD				sockaddrLen;
    805 			DNSSDAddressFamily	addressFamily;
    806 			char				addressUTF8[INET6_ADDRSTRLEN];
    807 			DWORD				addressLen = sizeof( addressUTF8 );
    808 			CComBSTR			address;
    809 			BOOL				ok;
    810 
    811 			ok = UTF8ToBSTR( hostNameUTF8, hostName );
    812 			require_action( ok, exit, err = kDNSServiceErr_Unknown );
    813 
    814 			switch ( rawAddress->sa_family )
    815 			{
    816 				case AF_INET:
    817 				{
    818 					addressFamily	= kDNSSDAddressFamily_IPv4;
    819 					sockaddrLen		= sizeof( sockaddr_in );
    820 				}
    821 				break;
    822 
    823 				case AF_INET6:
    824 				{
    825 					addressFamily	= kDNSSDAddressFamily_IPv6;
    826 					sockaddrLen		= sizeof( sockaddr_in6 );
    827 				}
    828 				break;
    829 			}
    830 
    831 			err = WSAAddressToStringA( ( LPSOCKADDR ) rawAddress, sockaddrLen, NULL, addressUTF8, &addressLen );
    832 			require_noerr( err, exit );
    833 			ok = UTF8ToBSTR( addressUTF8, address );
    834 			require_action( ok, exit, err = kDNSServiceErr_Unknown );
    835 
    836 			listener->GetAddrInfoReply( service, ( DNSSDFlags ) flags, ifIndex, hostName, addressFamily, address, ttl );
    837 		}
    838 		else
    839 		{
    840 			listener->GetAddrInfoFailed( service, ( DNSSDError ) errorCode );
    841 		}
    842 	}
    843 
    844 exit:
    845 
    846 	return;
    847 }
    848 
    849 
    850 void DNSSD_API
    851 CDNSSD::NATPortMappingReply
    852     (
    853     DNSServiceRef                    sdRef,
    854     DNSServiceFlags                  flags,
    855     uint32_t                         ifIndex,
    856     DNSServiceErrorType              errorCode,
    857     uint32_t                         externalAddress,   /* four byte IPv4 address in network byte order */
    858     DNSServiceProtocol               protocol,
    859     uint16_t                         internalPort,
    860     uint16_t                         externalPort,      /* may be different than the requested port     */
    861     uint32_t                         ttl,               /* may be different than the requested ttl      */
    862     void                             *context
    863     )
    864 {
    865 	CComObject<CDNSSDService> * service;
    866 	int err;
    867 
    868 	service = ( CComObject< CDNSSDService>* ) context;
    869 	require_action( service, exit, err = kDNSServiceErr_Unknown );
    870 
    871 	if ( !service->Stopped() )
    872 	{
    873 		INATPortMappingListener * listener;
    874 
    875 		listener = ( INATPortMappingListener* ) service->GetListener();
    876 		require_action( listener, exit, err = kDNSServiceErr_Unknown );
    877 
    878 		if ( !errorCode )
    879 		{
    880 			listener->MappingCreated( service, ( DNSSDFlags ) flags, ifIndex, externalAddress, ( DNSSDAddressFamily ) ( protocol & 0x8 ), ( DNSSDProtocol ) ( protocol & 0x80 ), internalPort, externalPort, ttl  );
    881 		}
    882 		else
    883 		{
    884 			listener->MappingFailed( service, ( DNSSDError ) errorCode );
    885 		}
    886 	}
    887 
    888 exit:
    889 
    890 	return;
    891 }
    892 
    893