]> git.saurik.com Git - apple/mdnsresponder.git/blobdiff - mDNSWindows/DLLX/DNSSD.cpp
mDNSResponder-212.1.tar.gz
[apple/mdnsresponder.git] / mDNSWindows / DLLX / DNSSD.cpp
diff --git a/mDNSWindows/DLLX/DNSSD.cpp b/mDNSWindows/DLLX/DNSSD.cpp
new file mode 100755 (executable)
index 0000000..84a8206
--- /dev/null
@@ -0,0 +1,892 @@
+// DNSSD.cpp : Implementation of CDNSSD\r
+\r
+#include "stdafx.h"\r
+#include "DNSSD.h"\r
+#include "DNSSDService.h"\r
+#include "TXTRecord.h"\r
+#include <dns_sd.h>\r
+#include <CommonServices.h>\r
+#include <DebugServices.h>\r
+#include "StringServices.h"\r
+\r
+\r
+// CDNSSD\r
+\r
+STDMETHODIMP CDNSSD::Browse(DNSSDFlags flags, ULONG ifIndex, BSTR regtype, BSTR domain, IBrowseListener* listener, IDNSSDService** browser )\r
+{\r
+       CComObject<CDNSSDService>       *       object          = NULL;\r
+       std::string                                             regtypeUTF8;\r
+       std::string                                             domainUTF8;\r
+       DNSServiceRef                                   sref            = NULL;\r
+       DNSServiceErrorType                             err                     = 0;\r
+       HRESULT                                                 hr                      = 0;\r
+       BOOL                                                    ok;\r
+\r
+       // Initialize\r
+       *browser = NULL;\r
+\r
+       // Convert BSTR params to utf8\r
+       ok = BSTRToUTF8( regtype, regtypeUTF8 );\r
+       require_action( ok, exit, err = kDNSServiceErr_BadParam );\r
+       ok = BSTRToUTF8( domain, domainUTF8 );\r
+       require_action( ok, exit, err = kDNSServiceErr_BadParam );\r
+\r
+       try\r
+       {\r
+               object = new CComObject<CDNSSDService>();\r
+       }\r
+       catch ( ... )\r
+       {\r
+               object = NULL;\r
+       }\r
+\r
+       require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );\r
+       hr = object->FinalConstruct();\r
+       require_action( hr == S_OK, exit, err = kDNSServiceErr_Unknown );\r
+       object->AddRef();\r
+\r
+       err = DNSServiceBrowse( &sref, flags, ifIndex, regtypeUTF8.c_str(), domainUTF8.c_str(), ( DNSServiceBrowseReply ) &BrowseReply, object );\r
+       require_noerr( err, exit );\r
+\r
+       object->SetServiceRef( sref );\r
+       object->SetListener( listener );\r
+\r
+       err = object->Run();\r
+       require_noerr( err, exit );\r
+\r
+       *browser = object;\r
+\r
+exit:\r
+\r
+       if ( err && object )\r
+       {\r
+               object->Release();\r
+       }\r
+\r
+       return err;\r
+}\r
+\r
+\r
+STDMETHODIMP CDNSSD::Resolve(DNSSDFlags flags, ULONG ifIndex, BSTR serviceName, BSTR regType, BSTR domain, IResolveListener* listener, IDNSSDService** service)\r
+{\r
+       CComObject<CDNSSDService>       *       object                  = NULL;\r
+       std::string                                             serviceNameUTF8;\r
+       std::string                                             regTypeUTF8;\r
+       std::string                                             domainUTF8;\r
+       DNSServiceRef                                   sref                    = NULL;\r
+       DNSServiceErrorType                             err                             = 0;\r
+       HRESULT                                                 hr                              = 0;\r
+       BOOL                                                    ok;\r
+\r
+       // Initialize\r
+       *service = NULL;\r
+\r
+       // Convert BSTR params to utf8\r
+       ok = BSTRToUTF8( serviceName, serviceNameUTF8 );\r
+       require_action( ok, exit, err = kDNSServiceErr_BadParam );\r
+       ok = BSTRToUTF8( regType, regTypeUTF8 );\r
+       require_action( ok, exit, err = kDNSServiceErr_BadParam );\r
+       ok = BSTRToUTF8( domain, domainUTF8 );\r
+       require_action( ok, exit, err = kDNSServiceErr_BadParam );\r
+\r
+       try\r
+       {\r
+               object = new CComObject<CDNSSDService>();\r
+       }\r
+       catch ( ... )\r
+       {\r
+               object = NULL;\r
+       }\r
+\r
+       require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );\r
+       hr = object->FinalConstruct();\r
+       require_action( hr == S_OK, exit, err = kDNSServiceErr_Unknown );\r
+       object->AddRef();\r
+\r
+       err = DNSServiceResolve( &sref, flags, ifIndex, serviceNameUTF8.c_str(), regTypeUTF8.c_str(), domainUTF8.c_str(), ( DNSServiceResolveReply ) &ResolveReply, object );\r
+       require_noerr( err, exit );\r
+\r
+       object->SetServiceRef( sref );\r
+       object->SetListener( listener );\r
+\r
+       err = object->Run();\r
+       require_noerr( err, exit );\r
+\r
+       *service = object;\r
+\r
+exit:\r
+\r
+       if ( err && object )\r
+       {\r
+               object->Release();\r
+       }\r
+\r
+       return err;\r
+}\r
+\r
+\r
+STDMETHODIMP CDNSSD::EnumerateDomains(DNSSDFlags flags, ULONG ifIndex, IDomainListener *listener, IDNSSDService **service)\r
+{\r
+       CComObject<CDNSSDService>       *       object                  = NULL;\r
+       DNSServiceRef                                   sref                    = NULL;\r
+       DNSServiceErrorType                             err                             = 0;\r
+       HRESULT                                                 hr                              = 0;\r
+\r
+       // Initialize\r
+       *service = NULL;\r
+\r
+       try\r
+       {\r
+               object = new CComObject<CDNSSDService>();\r
+       }\r
+       catch ( ... )\r
+       {\r
+               object = NULL;\r
+       }\r
+\r
+       require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );\r
+       hr = object->FinalConstruct();\r
+       require_action( hr == S_OK, exit, err = kDNSServiceErr_Unknown );\r
+       object->AddRef();\r
+\r
+       err = DNSServiceEnumerateDomains( &sref, flags, ifIndex, ( DNSServiceDomainEnumReply ) &DomainEnumReply, object );\r
+       require_noerr( err, exit );\r
+\r
+       object->SetServiceRef( sref );\r
+       object->SetListener( listener );\r
+\r
+       err = object->Run();\r
+       require_noerr( err, exit );\r
+\r
+       *service = object;\r
+\r
+exit:\r
+\r
+       if ( err && object )\r
+       {\r
+               object->Release();\r
+       }\r
+\r
+       return err;\r
+}\r
+\r
+\r
+STDMETHODIMP CDNSSD::Register(DNSSDFlags flags, ULONG ifIndex, BSTR serviceName, BSTR regType, BSTR domain, BSTR host, USHORT port, ITXTRecord *record, IRegisterListener *listener, IDNSSDService **service)\r
+{\r
+       CComObject<CDNSSDService>       *       object                  = NULL;\r
+       std::string                                             serviceNameUTF8;\r
+       std::string                                             regTypeUTF8;\r
+       std::string                                             domainUTF8;\r
+       std::string                                             hostUTF8;\r
+       const void                                      *       txtRecord               = NULL;\r
+       uint16_t                                                txtLen                  = 0;\r
+       DNSServiceRef                                   sref                    = NULL;\r
+       DNSServiceErrorType                             err                             = 0;\r
+       HRESULT                                                 hr                              = 0;\r
+       BOOL                                                    ok;\r
+\r
+       // Initialize\r
+       *service = NULL;\r
+\r
+       // Convert BSTR params to utf8\r
+       ok = BSTRToUTF8( serviceName, serviceNameUTF8 );\r
+       require_action( ok, exit, err = kDNSServiceErr_BadParam );\r
+       ok = BSTRToUTF8( regType, regTypeUTF8 );\r
+       require_action( ok, exit, err = kDNSServiceErr_BadParam );\r
+       ok = BSTRToUTF8( domain, domainUTF8 );\r
+       require_action( ok, exit, err = kDNSServiceErr_BadParam );\r
+       ok = BSTRToUTF8( host, hostUTF8 );\r
+       require_action( ok, exit, err = kDNSServiceErr_BadParam );\r
+\r
+       try\r
+       {\r
+               object = new CComObject<CDNSSDService>();\r
+       }\r
+       catch ( ... )\r
+       {\r
+               object = NULL;\r
+       }\r
+\r
+       require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );\r
+       hr = object->FinalConstruct();\r
+       require_action( hr == S_OK, exit, err = kDNSServiceErr_Unknown );\r
+       object->AddRef();\r
+\r
+       if ( record )\r
+       {\r
+               CComObject< CTXTRecord > * realTXTRecord;\r
+\r
+               realTXTRecord = ( CComObject< CTXTRecord >* ) record;\r
+\r
+               txtRecord       = realTXTRecord->GetBytes();\r
+               txtLen          = realTXTRecord->GetLen();\r
+       }\r
+\r
+       err = DNSServiceRegister( &sref, flags, ifIndex, serviceNameUTF8.c_str(), regTypeUTF8.c_str(), domainUTF8.c_str(), hostUTF8.c_str(), port, txtLen, txtRecord, ( DNSServiceRegisterReply ) &RegisterReply, object );\r
+       require_noerr( err, exit );\r
+\r
+       object->SetServiceRef( sref );\r
+       object->SetListener( listener );\r
+\r
+       err = object->Run();\r
+       require_noerr( err, exit );\r
+\r
+       *service = object;\r
+\r
+exit:\r
+\r
+       if ( err && object )\r
+       {\r
+               object->Release();\r
+       }\r
+\r
+       return err;\r
+}\r
+\r
+\r
+STDMETHODIMP CDNSSD::QueryRecord(DNSSDFlags flags, ULONG ifIndex, BSTR fullname, DNSSDRRType rrtype, DNSSDRRClass rrclass, IQueryRecordListener *listener, IDNSSDService **service)\r
+{\r
+       CComObject<CDNSSDService>       *       object                  = NULL;\r
+       DNSServiceRef                                   sref                    = NULL;\r
+       std::string                                             fullNameUTF8;\r
+       DNSServiceErrorType                             err                             = 0;\r
+       HRESULT                                                 hr                              = 0;\r
+       BOOL                                                    ok;\r
+\r
+       // Initialize\r
+       *service = NULL;\r
+\r
+       // Convert BSTR params to utf8\r
+       ok = BSTRToUTF8( fullname, fullNameUTF8 );\r
+       require_action( ok, exit, err = kDNSServiceErr_BadParam );\r
+\r
+       try\r
+       {\r
+               object = new CComObject<CDNSSDService>();\r
+       }\r
+       catch ( ... )\r
+       {\r
+               object = NULL;\r
+       }\r
+\r
+       require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );\r
+       hr = object->FinalConstruct();\r
+       require_action( hr == S_OK, exit, err = kDNSServiceErr_Unknown );\r
+       object->AddRef();\r
+\r
+       err = DNSServiceQueryRecord( &sref, flags, ifIndex, fullNameUTF8.c_str(), ( uint16_t ) rrtype, ( uint16_t ) rrclass, ( DNSServiceQueryRecordReply ) &QueryRecordReply, object );\r
+       require_noerr( err, exit );\r
+\r
+       object->SetServiceRef( sref );\r
+       object->SetListener( listener );\r
+\r
+       err = object->Run();\r
+       require_noerr( err, exit );\r
+\r
+       *service = object;\r
+\r
+exit:\r
+\r
+       if ( err && object )\r
+       {\r
+               object->Release();\r
+       }\r
+\r
+       return err;\r
+}\r
+\r
+\r
+STDMETHODIMP CDNSSD::GetAddrInfo(DNSSDFlags flags, ULONG ifIndex, DNSSDAddressFamily addressFamily, BSTR hostName, IGetAddrInfoListener *listener, IDNSSDService **service)\r
+{\r
+       CComObject<CDNSSDService>       *       object                  = NULL;\r
+       DNSServiceRef                                   sref                    = NULL;\r
+       std::string                                             hostNameUTF8;\r
+       DNSServiceErrorType                             err                             = 0;\r
+       HRESULT                                                 hr                              = 0;\r
+       BOOL                                                    ok;\r
+\r
+       // Initialize\r
+       *service = NULL;\r
+\r
+       // Convert BSTR params to utf8\r
+       ok = BSTRToUTF8( hostName, hostNameUTF8 );\r
+       require_action( ok, exit, err = kDNSServiceErr_BadParam );\r
+\r
+       try\r
+       {\r
+               object = new CComObject<CDNSSDService>();\r
+       }\r
+       catch ( ... )\r
+       {\r
+               object = NULL;\r
+       }\r
+\r
+       require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );\r
+       hr = object->FinalConstruct();\r
+       require_action( hr == S_OK, exit, err = kDNSServiceErr_Unknown );\r
+       object->AddRef();\r
+\r
+       err = DNSServiceGetAddrInfo( &sref, flags, ifIndex, addressFamily, hostNameUTF8.c_str(), ( DNSServiceGetAddrInfoReply ) &GetAddrInfoReply, object );\r
+       require_noerr( err, exit );\r
+\r
+       object->SetServiceRef( sref );\r
+       object->SetListener( listener );\r
+\r
+       err = object->Run();\r
+       require_noerr( err, exit );\r
+\r
+       *service = object;\r
+\r
+exit:\r
+\r
+       if ( err && object )\r
+       {\r
+               object->Release();\r
+       }\r
+\r
+       return err;\r
+}\r
+\r
+\r
+STDMETHODIMP CDNSSD::CreateConnection(IDNSSDService **service)\r
+{\r
+       CComObject<CDNSSDService>       *       object  = NULL;\r
+       DNSServiceRef                                   sref    = NULL;\r
+       DNSServiceErrorType                             err             = 0;\r
+       HRESULT                                                 hr              = 0;\r
+\r
+       // Initialize\r
+       *service = NULL;\r
+\r
+       try\r
+       {\r
+               object = new CComObject<CDNSSDService>();\r
+       }\r
+       catch ( ... )\r
+       {\r
+               object = NULL;\r
+       }\r
+\r
+       require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );\r
+       hr = object->FinalConstruct();\r
+       require_action( hr == S_OK, exit, err = kDNSServiceErr_Unknown );\r
+       object->AddRef();\r
+\r
+       err = DNSServiceCreateConnection( &sref );\r
+       require_noerr( err, exit );\r
+\r
+       object->SetServiceRef( sref );\r
+\r
+       *service = object;\r
+\r
+exit:\r
+\r
+       if ( err && object )\r
+       {\r
+               object->Release();\r
+       }\r
+\r
+       return err;\r
+}\r
+\r
+\r
+STDMETHODIMP CDNSSD::NATPortMappingCreate(DNSSDFlags flags, ULONG ifIndex, DNSSDAddressFamily addressFamily, DNSSDProtocol protocol, USHORT internalPort, USHORT externalPort, ULONG ttl, INATPortMappingListener *listener, IDNSSDService **service)\r
+{\r
+       CComObject<CDNSSDService>       *       object                  = NULL;\r
+       DNSServiceRef                                   sref                    = NULL;\r
+       DNSServiceProtocol                              prot                    = 0;\r
+       DNSServiceErrorType                             err                             = 0;\r
+       HRESULT                                                 hr                              = 0;\r
+\r
+       // Initialize\r
+       *service = NULL;\r
+\r
+       try\r
+       {\r
+               object = new CComObject<CDNSSDService>();\r
+       }\r
+       catch ( ... )\r
+       {\r
+               object = NULL;\r
+       }\r
+\r
+       require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );\r
+       hr = object->FinalConstruct();\r
+       require_action( hr == S_OK, exit, err = kDNSServiceErr_Unknown );\r
+       object->AddRef();\r
+\r
+       prot = ( addressFamily | protocol );\r
+\r
+       err = DNSServiceNATPortMappingCreate( &sref, flags, ifIndex, prot, internalPort, externalPort, ttl, ( DNSServiceNATPortMappingReply ) &NATPortMappingReply, object );\r
+       require_noerr( err, exit );\r
+\r
+       object->SetServiceRef( sref );\r
+       object->SetListener( listener );\r
+\r
+       err = object->Run();\r
+       require_noerr( err, exit );\r
+\r
+       *service = object;\r
+\r
+exit:\r
+\r
+       if ( err && object )\r
+       {\r
+               object->Release();\r
+       }\r
+\r
+       return err;\r
+}\r
+\r
+\r
+STDMETHODIMP CDNSSD::GetProperty(BSTR prop, VARIANT * value )\r
+{\r
+       std::string                     propUTF8;\r
+       std::vector< BYTE >     byteArray;\r
+       SAFEARRAY               *       psa                     = NULL;\r
+       BYTE                    *       pData           = NULL;\r
+       uint32_t                        elems           = 0;\r
+       DNSServiceErrorType     err                     = 0;\r
+       BOOL                            ok = TRUE;\r
+\r
+       // Convert BSTR params to utf8\r
+       ok = BSTRToUTF8( prop, propUTF8 );\r
+       require_action( ok, exit, err = kDNSServiceErr_BadParam );\r
+\r
+       // Setup the byte array\r
+       require_action( V_VT( value ) == ( VT_ARRAY|VT_UI1 ), exit, err = kDNSServiceErr_Unknown );\r
+       psa = V_ARRAY( value );\r
+       require_action( psa, exit, err = kDNSServiceErr_Unknown );\r
+       require_action( SafeArrayGetDim( psa ) == 1, exit, err = kDNSServiceErr_Unknown );\r
+       byteArray.reserve( psa->rgsabound[0].cElements );\r
+       byteArray.assign( byteArray.capacity(), 0 );\r
+       elems = ( uint32_t ) byteArray.capacity();\r
+\r
+       // Call the function and package the return value in the Variant\r
+       err = DNSServiceGetProperty( propUTF8.c_str(), &byteArray[ 0 ], &elems );\r
+       require_noerr( err, exit );\r
+       ok = ByteArrayToVariant( &byteArray[ 0 ], elems, value );\r
+       require_action( ok, exit, err = kDNSSDError_Unknown );\r
+\r
+exit:\r
+\r
+       if ( psa )\r
+       {\r
+               SafeArrayUnaccessData( psa );\r
+               psa = NULL;\r
+       }\r
+\r
+       return err;\r
+}\r
+\r
+\r
+void DNSSD_API
+CDNSSD::DomainEnumReply
+    (
+    DNSServiceRef                       sdRef,
+    DNSServiceFlags                     flags,
+    uint32_t                            ifIndex,
+    DNSServiceErrorType                 errorCode,
+    const char                          *replyDomainUTF8,
+    void                                *context
+    )\r
+{\r
+       CComObject<CDNSSDService> * service;\r
+       int err;\r
+       \r
+       service = ( CComObject< CDNSSDService>* ) context;\r
+       require_action( service, exit, err = kDNSServiceErr_Unknown );\r
+\r
+       if ( !service->Stopped() )\r
+       {\r
+               IDomainListener * listener;\r
+\r
+               listener = ( IDomainListener* ) service->GetListener();\r
+               require_action( listener, exit, err = kDNSServiceErr_Unknown );\r
+\r
+               if ( !errorCode )\r
+               {\r
+                       CComBSTR replyDomain;\r
+               \r
+                       UTF8ToBSTR( replyDomainUTF8, replyDomain );\r
+\r
+                       if ( flags & kDNSServiceFlagsAdd )\r
+                       {\r
+                               listener->DomainFound( service, ( DNSSDFlags ) flags, ifIndex, replyDomain );\r
+                       }\r
+                       else\r
+                       {\r
+                               listener->DomainLost( service, ( DNSSDFlags ) flags, ifIndex, replyDomain );\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       listener->EnumDomainsFailed( service, ( DNSSDError ) errorCode );\r
+               }\r
+       }\r
+\r
+exit:\r
+\r
+       return;\r
+}\r
+\r
+\r
+void DNSSD_API
+CDNSSD::BrowseReply
+               (
+               DNSServiceRef                       sdRef,
+               DNSServiceFlags                     flags,
+               uint32_t                            ifIndex,
+               DNSServiceErrorType                 errorCode,
+               const char                          *serviceNameUTF8,
+               const char                          *regTypeUTF8,
+               const char                          *replyDomainUTF8,
+               void                                *context
+               )\r
+{\r
+       CComObject<CDNSSDService> * service;\r
+       int err;\r
+       \r
+       service = ( CComObject< CDNSSDService>* ) context;\r
+       require_action( service, exit, err = kDNSServiceErr_Unknown );\r
+\r
+       if ( !service->Stopped() )\r
+       {\r
+               IBrowseListener * listener;\r
+\r
+               listener = ( IBrowseListener* ) service->GetListener();\r
+               require_action( listener, exit, err = kDNSServiceErr_Unknown );\r
+\r
+               if ( !errorCode )\r
+               {\r
+                       CComBSTR        serviceName;\r
+                       CComBSTR        regType;\r
+                       CComBSTR        replyDomain;\r
+               \r
+                       UTF8ToBSTR( serviceNameUTF8, serviceName );\r
+                       UTF8ToBSTR( regTypeUTF8, regType );\r
+                       UTF8ToBSTR( replyDomainUTF8, replyDomain );\r
+\r
+                       if ( flags & kDNSServiceFlagsAdd )\r
+                       {\r
+                               listener->ServiceFound( service, ( DNSSDFlags ) flags, ifIndex, serviceName, regType, replyDomain );\r
+                       }\r
+                       else\r
+                       {\r
+                               listener->ServiceLost( service, ( DNSSDFlags ) flags, ifIndex, serviceName, regType, replyDomain );\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       listener->BrowseFailed( service, ( DNSSDError ) errorCode );\r
+               }\r
+       }\r
+\r
+exit:\r
+\r
+       return;\r
+}\r
+\r
+\r
+void DNSSD_API\r
+CDNSSD::ResolveReply\r
+               (
+               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\r
+               )\r
+{\r
+       CComObject<CDNSSDService> * service;\r
+       int err;\r
+       \r
+       service = ( CComObject< CDNSSDService>* ) context;\r
+       require_action( service, exit, err = kDNSServiceErr_Unknown );\r
+\r
+       if ( !service->Stopped() )\r
+       {\r
+               IResolveListener * listener;\r
+\r
+               listener = ( IResolveListener* ) service->GetListener();\r
+               require_action( listener, exit, err = kDNSServiceErr_Unknown );\r
+\r
+               if ( !errorCode )\r
+               {\r
+                       CComBSTR                                        fullName;\r
+                       CComBSTR                                        hostName;\r
+                       CComBSTR                                        regType;\r
+                       CComBSTR                                        replyDomain;\r
+                       CComObject< CTXTRecord >*       record;\r
+                       BOOL                                            ok;\r
+\r
+                       ok = UTF8ToBSTR( fullNameUTF8, fullName );\r
+                       require_action( ok, exit, err = kDNSServiceErr_Unknown );\r
+                       ok = UTF8ToBSTR( hostNameUTF8, hostName );\r
+                       require_action( ok, exit, err = kDNSServiceErr_Unknown );\r
+\r
+                       try\r
+                       {\r
+                               record = new CComObject<CTXTRecord>();\r
+                       }\r
+                       catch ( ... )\r
+                       {\r
+                               record = NULL;\r
+                       }\r
+\r
+                       require_action( record, exit, err = kDNSServiceErr_NoMemory );\r
+                       record->AddRef();\r
+\r
+                       char buf[ 64 ];\r
+                       sprintf( buf, "txtLen = %d", txtLen );\r
+                       OutputDebugStringA( buf );\r
+\r
+                       if ( txtLen > 0 )\r
+                       {\r
+                               record->SetBytes( txtRecord, txtLen );\r
+                       }\r
+\r
+                       listener->ServiceResolved( service, ( DNSSDFlags ) flags, ifIndex, fullName, hostName, port, record );\r
+               }\r
+               else\r
+               {\r
+                       listener->ResolveFailed( service, ( DNSSDError ) errorCode );\r
+               }\r
+       }\r
+\r
+exit:\r
+\r
+       return;\r
+}\r
+\r
+\r
+void DNSSD_API
+CDNSSD::RegisterReply
+               (
+               DNSServiceRef                       sdRef,
+               DNSServiceFlags                     flags,
+               DNSServiceErrorType                 errorCode,
+               const char                          *serviceNameUTF8,
+               const char                          *regTypeUTF8,
+               const char                          *domainUTF8,
+               void                                *context
+               )\r
+{\r
+       CComObject<CDNSSDService> * service;\r
+       int err;\r
+       \r
+       service = ( CComObject< CDNSSDService>* ) context;\r
+       require_action( service, exit, err = kDNSServiceErr_Unknown );\r
+\r
+       if ( !service->Stopped() )\r
+       {\r
+               IRegisterListener * listener;\r
+\r
+               listener = ( IRegisterListener* ) service->GetListener();\r
+               require_action( listener, exit, err = kDNSServiceErr_Unknown );\r
+\r
+               if ( !errorCode )\r
+               {\r
+                       CComBSTR                                        serviceName;\r
+                       CComBSTR                                        regType;\r
+                       CComBSTR                                        domain;\r
+                       BOOL                                            ok;\r
+\r
+                       ok = UTF8ToBSTR( serviceNameUTF8, serviceName );\r
+                       require_action( ok, exit, err = kDNSServiceErr_Unknown );\r
+                       ok = UTF8ToBSTR( regTypeUTF8, regType );\r
+                       require_action( ok, exit, err = kDNSServiceErr_Unknown );\r
+                       ok = UTF8ToBSTR( domainUTF8, domain );\r
+                       require_action( ok, exit, err = kDNSServiceErr_Unknown );\r
+\r
+                       listener->ServiceRegistered( service, ( DNSSDFlags ) flags, serviceName, regType, domain );\r
+               }\r
+               else\r
+               {\r
+                       listener->ServiceRegisterFailed( service, ( DNSSDError ) errorCode );\r
+               }\r
+       }\r
+\r
+exit:\r
+\r
+       return;\r
+}\r
+\r
+\r
+void DNSSD_API
+CDNSSD::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
+               )\r
+{\r
+       CComObject<CDNSSDService> * service;\r
+       int err;\r
+       \r
+       service = ( CComObject< CDNSSDService>* ) context;\r
+       require_action( service, exit, err = kDNSServiceErr_Unknown );\r
+\r
+       if ( !service->Stopped() )\r
+       {\r
+               IQueryRecordListener * listener;\r
+\r
+               listener = ( IQueryRecordListener* ) service->GetListener();\r
+               require_action( listener, exit, err = kDNSServiceErr_Unknown );\r
+\r
+               if ( !errorCode )\r
+               {\r
+                       CComBSTR        fullName;\r
+                       VARIANT         var;\r
+                       BOOL            ok;\r
+\r
+                       ok = UTF8ToBSTR( fullNameUTF8, fullName );\r
+                       require_action( ok, exit, err = kDNSServiceErr_Unknown );\r
+                       ok = ByteArrayToVariant( rdata, rdlen, &var );\r
+                       require_action( ok, exit, err = kDNSServiceErr_Unknown );\r
+\r
+                       listener->QueryRecordAnswered( service, ( DNSSDFlags ) flags, ifIndex, fullName, ( DNSSDRRType ) rrtype, ( DNSSDRRClass ) rrclass, var, ttl );\r
+               }\r
+               else\r
+               {\r
+                       listener->QueryRecordFailed( service, ( DNSSDError ) errorCode );\r
+               }\r
+       }\r
+\r
+exit:\r
+\r
+       return;\r
+}\r
+\r
+\r
+void DNSSD_API
+CDNSSD::GetAddrInfoReply
+               (
+               DNSServiceRef                    sdRef,
+               DNSServiceFlags                  flags,
+               uint32_t                         ifIndex,
+               DNSServiceErrorType              errorCode,
+               const char                       *hostNameUTF8,
+               const struct sockaddr            *rawAddress,
+               uint32_t                         ttl,
+               void                             *context
+               )\r
+{\r
+       CComObject<CDNSSDService> * service;\r
+       int err;\r
+       \r
+       service = ( CComObject< CDNSSDService>* ) context;\r
+       require_action( service, exit, err = kDNSServiceErr_Unknown );\r
+\r
+       if ( !service->Stopped() )\r
+       {\r
+               IGetAddrInfoListener * listener;\r
+\r
+               listener = ( IGetAddrInfoListener* ) service->GetListener();\r
+               require_action( listener, exit, err = kDNSServiceErr_Unknown );\r
+\r
+               if ( !errorCode )\r
+               {\r
+                       CComBSTR                        hostName;\r
+                       DWORD                           sockaddrLen;\r
+                       DNSSDAddressFamily      addressFamily;\r
+                       char                            addressUTF8[INET6_ADDRSTRLEN];\r
+                       DWORD                           addressLen = sizeof( addressUTF8 );\r
+                       CComBSTR                        address;\r
+                       BOOL                            ok;\r
+\r
+                       ok = UTF8ToBSTR( hostNameUTF8, hostName );\r
+                       require_action( ok, exit, err = kDNSServiceErr_Unknown );\r
+\r
+                       switch ( rawAddress->sa_family )\r
+                       {\r
+                               case AF_INET:\r
+                               {\r
+                                       addressFamily   = kDNSSDAddressFamily_IPv4;\r
+                                       sockaddrLen             = sizeof( sockaddr_in );\r
+                               }\r
+                               break;\r
+\r
+                               case AF_INET6:\r
+                               {\r
+                                       addressFamily   = kDNSSDAddressFamily_IPv6;\r
+                                       sockaddrLen             = sizeof( sockaddr_in6 );\r
+                               }\r
+                               break;\r
+                       }\r
+\r
+                       err = WSAAddressToStringA( ( LPSOCKADDR ) rawAddress, sockaddrLen, NULL, addressUTF8, &addressLen );\r
+                       require_noerr( err, exit );\r
+                       ok = UTF8ToBSTR( addressUTF8, address );\r
+                       require_action( ok, exit, err = kDNSServiceErr_Unknown );\r
+\r
+                       listener->GetAddrInfoReply( service, ( DNSSDFlags ) flags, ifIndex, hostName, addressFamily, address, ttl );\r
+               }\r
+               else\r
+               {\r
+                       listener->GetAddrInfoFailed( service, ( DNSSDError ) errorCode );\r
+               }\r
+       }\r
+\r
+exit:\r
+\r
+       return;\r
+}\r
+\r
+\r
+void DNSSD_API
+CDNSSD::NATPortMappingReply
+    (
+    DNSServiceRef                    sdRef,
+    DNSServiceFlags                  flags,
+    uint32_t                         ifIndex,
+    DNSServiceErrorType              errorCode,
+    uint32_t                         externalAddress,   /* four byte IPv4 address in network byte order */
+    DNSServiceProtocol               protocol,
+    uint16_t                         internalPort,
+    uint16_t                         externalPort,      /* may be different than the requested port     */
+    uint32_t                         ttl,               /* may be different than the requested ttl      */
+    void                             *context
+    )\r
+{\r
+       CComObject<CDNSSDService> * service;\r
+       int err;\r
+       \r
+       service = ( CComObject< CDNSSDService>* ) context;\r
+       require_action( service, exit, err = kDNSServiceErr_Unknown );\r
+\r
+       if ( !service->Stopped() )\r
+       {\r
+               INATPortMappingListener * listener;\r
+\r
+               listener = ( INATPortMappingListener* ) service->GetListener();\r
+               require_action( listener, exit, err = kDNSServiceErr_Unknown );\r
+\r
+               if ( !errorCode )\r
+               {\r
+                       listener->MappingCreated( service, ( DNSSDFlags ) flags, ifIndex, externalAddress, ( DNSSDAddressFamily ) ( protocol & 0x8 ), ( DNSSDProtocol ) ( protocol & 0x80 ), internalPort, externalPort, ttl  );\r
+               }\r
+               else\r
+               {\r
+                       listener->MappingFailed( service, ( DNSSDError ) errorCode );\r
+               }\r
+       }\r
+\r
+exit:\r
+\r
+       return;\r
+}\r
+\r