• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
Browse(DNSSDFlags flags,ULONG ifIndex,BSTR regtype,BSTR domain,IBrowseListener * listener,IDNSSDService ** browser)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 
Resolve(DNSSDFlags flags,ULONG ifIndex,BSTR serviceName,BSTR regType,BSTR domain,IResolveListener * listener,IDNSSDService ** service)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 
EnumerateDomains(DNSSDFlags flags,ULONG ifIndex,IDomainListener * listener,IDNSSDService ** service)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 
Register(DNSSDFlags flags,ULONG ifIndex,BSTR serviceName,BSTR regType,BSTR domain,BSTR host,USHORT port,ITXTRecord * record,IRegisterListener * listener,IDNSSDService ** service)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 
QueryRecord(DNSSDFlags flags,ULONG ifIndex,BSTR fullname,DNSSDRRType rrtype,DNSSDRRClass rrclass,IQueryRecordListener * listener,IDNSSDService ** service)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 
GetAddrInfo(DNSSDFlags flags,ULONG ifIndex,DNSSDAddressFamily addressFamily,BSTR hostName,IGetAddrInfoListener * listener,IDNSSDService ** service)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 
CreateConnection(IDNSSDService ** service)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 
NATPortMappingCreate(DNSSDFlags flags,ULONG ifIndex,DNSSDAddressFamily addressFamily,DNSSDProtocol protocol,USHORT internalPort,USHORT externalPort,ULONG ttl,INATPortMappingListener * listener,IDNSSDService ** service)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 
GetProperty(BSTR prop,VARIANT * value)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
DomainEnumReply(DNSServiceRef sdRef,DNSServiceFlags flags,uint32_t ifIndex,DNSServiceErrorType errorCode,const char * replyDomainUTF8,void * context)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
BrowseReply(DNSServiceRef sdRef,DNSServiceFlags flags,uint32_t ifIndex,DNSServiceErrorType errorCode,const char * serviceNameUTF8,const char * regTypeUTF8,const char * replyDomainUTF8,void * context)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
ResolveReply(DNSServiceRef sdRef,DNSServiceFlags flags,uint32_t ifIndex,DNSServiceErrorType errorCode,const char * fullNameUTF8,const char * hostNameUTF8,uint16_t port,uint16_t txtLen,const unsigned char * txtRecord,void * context)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
RegisterReply(DNSServiceRef sdRef,DNSServiceFlags flags,DNSServiceErrorType errorCode,const char * serviceNameUTF8,const char * regTypeUTF8,const char * domainUTF8,void * context)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
QueryRecordReply(DNSServiceRef sdRef,DNSServiceFlags flags,uint32_t ifIndex,DNSServiceErrorType errorCode,const char * fullNameUTF8,uint16_t rrtype,uint16_t rrclass,uint16_t rdlen,const void * rdata,uint32_t ttl,void * context)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
GetAddrInfoReply(DNSServiceRef sdRef,DNSServiceFlags flags,uint32_t ifIndex,DNSServiceErrorType errorCode,const char * hostNameUTF8,const struct sockaddr * rawAddress,uint32_t ttl,void * context)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
NATPortMappingReply(DNSServiceRef sdRef,DNSServiceFlags flags,uint32_t ifIndex,DNSServiceErrorType errorCode,uint32_t externalAddress,DNSServiceProtocol protocol,uint16_t internalPort,uint16_t externalPort,uint32_t ttl,void * context)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