1/* -*- Mode: C; tab-width: 4 -*- 2 * 3 * Copyright (c) 2009 Apple Computer, Inc. All rights reserved. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 19 20#pragma warning(disable:4995) 21 22 23 24#include "stdafx.h" 25 26#include <strsafe.h> 27 28#include "DNSSDService.h" 29 30#include "DNSSDEventManager.h" 31 32#include "DNSSDRecord.h" 33 34#include "TXTRecord.h" 35 36#include "StringServices.h" 37 38#include <DebugServices.h> 39 40 41 42 43 44#define WM_SOCKET (WM_APP + 100) 45 46 47 48 49 50// CDNSSDService 51 52 53 54BOOL CDNSSDService::m_registeredWindowClass = FALSE; 55 56HWND CDNSSDService::m_hiddenWindow = NULL; 57 58CDNSSDService::SocketMap CDNSSDService::m_socketMap; 59 60 61 62 63 64HRESULT CDNSSDService::FinalConstruct() 65 66{ 67 68 DNSServiceErrorType err = 0; 69 70 HRESULT hr = S_OK; 71 72 73 74 m_isPrimary = TRUE; 75 76 err = DNSServiceCreateConnection( &m_primary ); 77 78 require_action( !err, exit, hr = E_FAIL ); 79 80 81 82 if ( !m_hiddenWindow ) 83 84 { 85 86 TCHAR windowClassName[ 256 ]; 87 88 89 90 StringCchPrintf( windowClassName, sizeof( windowClassName ) / sizeof( TCHAR ), TEXT( "Bonjour Hidden Window %d" ), GetProcessId( NULL ) ); 91 92 93 94 if ( !m_registeredWindowClass ) 95 96 { 97 98 WNDCLASS wc; 99 100 ATOM atom; 101 102 103 104 wc.style = 0; 105 106 wc.lpfnWndProc = WndProc; 107 108 wc.cbClsExtra = 0; 109 110 wc.cbWndExtra = 0; 111 112 wc.hInstance = NULL; 113 114 wc.hIcon = NULL; 115 116 wc.hCursor = NULL; 117 118 wc.hbrBackground = NULL; 119 120 wc.lpszMenuName = NULL; 121 122 wc.lpszClassName = windowClassName; 123 124 125 126 atom = RegisterClass(&wc); 127 128 require_action( atom != NULL, exit, hr = E_FAIL ); 129 130 131 132 m_registeredWindowClass = TRUE; 133 134 } 135 136 137 138 m_hiddenWindow = CreateWindow( windowClassName, windowClassName, WS_OVERLAPPED, 0, 0, 0, 0, NULL, NULL, GetModuleHandle( NULL ), NULL ); 139 140 require_action( m_hiddenWindow != NULL, exit, hr = E_FAIL ); 141 142 } 143 144 145 146 err = WSAAsyncSelect( DNSServiceRefSockFD( m_primary ), m_hiddenWindow, WM_SOCKET, FD_READ ); 147 148 require_action( !err, exit, hr = E_FAIL ); 149 150 151 152 m_socketMap[ DNSServiceRefSockFD( m_primary ) ] = this; 153 154 155 156exit: 157 158 159 160 return hr; 161 162} 163 164 165 166 167 168void CDNSSDService::FinalRelease() 169 170{ 171 172 dlog( kDebugLevelTrace, "FinalRelease()\n" ); 173 174 Stop(); 175 176} 177 178 179 180 181 182STDMETHODIMP CDNSSDService::EnumerateDomains(DNSSDFlags flags, ULONG ifIndex, IDNSSDEventManager *eventManager, IDNSSDService **service) 183 184{ 185 186 CComObject<CDNSSDService> * object = NULL; 187 188 DNSServiceRef subord = NULL; 189 190 DNSServiceErrorType err = 0; 191 192 HRESULT hr = 0; 193 194 195 196 check( m_primary ); 197 198 199 200 // Initialize 201 202 *service = NULL; 203 204 205 206 try 207 208 { 209 210 object = new CComObject<CDNSSDService>(); 211 212 } 213 214 catch ( ... ) 215 216 { 217 218 object = NULL; 219 220 } 221 222 223 224 require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory ); 225 226 object->AddRef(); 227 228 229 230 subord = m_primary; 231 232 err = DNSServiceEnumerateDomains( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, ( DNSServiceDomainEnumReply ) &DomainEnumReply, object ); 233 234 require_noerr( err, exit ); 235 236 237 238 object->SetPrimaryRef( m_primary ); 239 240 object->SetSubordRef( subord ); 241 242 object->SetEventManager( eventManager ); 243 244 245 246 *service = object; 247 248 249 250exit: 251 252 253 254 if ( err && object ) 255 256 { 257 258 object->Release(); 259 260 } 261 262 263 264 return err; 265 266} 267 268 269 270 271 272STDMETHODIMP CDNSSDService::Browse(DNSSDFlags flags, ULONG ifIndex, BSTR regtype, BSTR domain, IDNSSDEventManager* eventManager, IDNSSDService** service ) 273 274{ 275 276 CComObject<CDNSSDService> * object = NULL; 277 278 std::string regtypeUTF8; 279 280 std::string domainUTF8; 281 282 DNSServiceRef subord = NULL; 283 284 DNSServiceErrorType err = 0; 285 286 HRESULT hr = 0; 287 288 BOOL ok; 289 290 291 292 check( m_primary ); 293 294 295 296 // Initialize 297 298 *service = NULL; 299 300 301 302 // Convert BSTR params to utf8 303 304 ok = BSTRToUTF8( regtype, regtypeUTF8 ); 305 306 require_action( ok, exit, err = kDNSServiceErr_BadParam ); 307 308 ok = BSTRToUTF8( domain, domainUTF8 ); 309 310 require_action( ok, exit, err = kDNSServiceErr_BadParam ); 311 312 313 314 try 315 316 { 317 318 object = new CComObject<CDNSSDService>(); 319 320 } 321 322 catch ( ... ) 323 324 { 325 326 object = NULL; 327 328 } 329 330 331 332 require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory ); 333 334 object->AddRef(); 335 336 337 338 subord = m_primary; 339 340 err = DNSServiceBrowse( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, regtypeUTF8.c_str(), ( domainUTF8.size() > 0 ) ? domainUTF8.c_str() : NULL, ( DNSServiceBrowseReply ) &BrowseReply, object ); 341 342 require_noerr( err, exit ); 343 344 345 346 object->SetPrimaryRef( m_primary ); 347 348 object->SetSubordRef( subord ); 349 350 object->SetEventManager( eventManager ); 351 352 353 354 *service = object; 355 356 357 358exit: 359 360 361 362 if ( err && object ) 363 364 { 365 366 object->Release(); 367 368 } 369 370 371 372 return err; 373 374} 375 376 377 378 379 380STDMETHODIMP CDNSSDService::Resolve(DNSSDFlags flags, ULONG ifIndex, BSTR serviceName, BSTR regType, BSTR domain, IDNSSDEventManager* eventManager, IDNSSDService** service) 381 382{ 383 384 CComObject<CDNSSDService> * object = NULL; 385 386 std::string serviceNameUTF8; 387 388 std::string regTypeUTF8; 389 390 std::string domainUTF8; 391 392 DNSServiceRef subord = NULL; 393 394 DNSServiceErrorType err = 0; 395 396 HRESULT hr = 0; 397 398 BOOL ok; 399 400 401 402 check( m_primary ); 403 404 405 406 // Initialize 407 408 *service = NULL; 409 410 411 412 // Convert BSTR params to utf8 413 414 ok = BSTRToUTF8( serviceName, serviceNameUTF8 ); 415 416 require_action( ok, exit, err = kDNSServiceErr_BadParam ); 417 418 ok = BSTRToUTF8( regType, regTypeUTF8 ); 419 420 require_action( ok, exit, err = kDNSServiceErr_BadParam ); 421 422 ok = BSTRToUTF8( domain, domainUTF8 ); 423 424 require_action( ok, exit, err = kDNSServiceErr_BadParam ); 425 426 427 428 try 429 430 { 431 432 object = new CComObject<CDNSSDService>(); 433 434 } 435 436 catch ( ... ) 437 438 { 439 440 object = NULL; 441 442 } 443 444 445 446 require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory ); 447 448 object->AddRef(); 449 450 451 452 subord = m_primary; 453 454 err = DNSServiceResolve( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, serviceNameUTF8.c_str(), regTypeUTF8.c_str(), domainUTF8.c_str(), ( DNSServiceResolveReply ) &ResolveReply, object ); 455 456 require_noerr( err, exit ); 457 458 459 460 object->SetPrimaryRef( m_primary ); 461 462 object->SetSubordRef( subord ); 463 464 object->SetEventManager( eventManager ); 465 466 467 468 *service = object; 469 470 471 472exit: 473 474 475 476 if ( err && object ) 477 478 { 479 480 object->Release(); 481 482 } 483 484 485 486 return err; 487 488} 489 490 491 492 493 494STDMETHODIMP CDNSSDService::Register(DNSSDFlags flags, ULONG ifIndex, BSTR serviceName, BSTR regType, BSTR domain, BSTR host, USHORT port, ITXTRecord *record, IDNSSDEventManager *eventManager, IDNSSDService **service) 495 496{ 497 498 CComObject<CDNSSDService> * object = NULL; 499 500 std::string serviceNameUTF8; 501 502 std::string regTypeUTF8; 503 504 std::string domainUTF8; 505 506 std::string hostUTF8; 507 508 const void * txtRecord = NULL; 509 510 uint16_t txtLen = 0; 511 512 DNSServiceRef subord = NULL; 513 514 DNSServiceErrorType err = 0; 515 516 HRESULT hr = 0; 517 518 BOOL ok; 519 520 521 522 check( m_primary ); 523 524 525 526 // Initialize 527 528 *service = NULL; 529 530 531 532 // Convert BSTR params to utf8 533 534 ok = BSTRToUTF8( serviceName, serviceNameUTF8 ); 535 536 require_action( ok, exit, err = kDNSServiceErr_BadParam ); 537 538 ok = BSTRToUTF8( regType, regTypeUTF8 ); 539 540 require_action( ok, exit, err = kDNSServiceErr_BadParam ); 541 542 ok = BSTRToUTF8( domain, domainUTF8 ); 543 544 require_action( ok, exit, err = kDNSServiceErr_BadParam ); 545 546 ok = BSTRToUTF8( host, hostUTF8 ); 547 548 require_action( ok, exit, err = kDNSServiceErr_BadParam ); 549 550 551 552 try 553 554 { 555 556 object = new CComObject<CDNSSDService>(); 557 558 } 559 560 catch ( ... ) 561 562 { 563 564 object = NULL; 565 566 } 567 568 569 570 require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory ); 571 572 object->AddRef(); 573 574 575 576 if ( record ) 577 578 { 579 580 CComObject< CTXTRecord > * realTXTRecord; 581 582 583 584 realTXTRecord = ( CComObject< CTXTRecord >* ) record; 585 586 587 588 txtRecord = realTXTRecord->GetBytes(); 589 590 txtLen = realTXTRecord->GetLen(); 591 592 } 593 594 595 596 subord = m_primary; 597 598 err = DNSServiceRegister( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, serviceNameUTF8.c_str(), regTypeUTF8.c_str(), ( domainUTF8.size() > 0 ) ? domainUTF8.c_str() : NULL, hostUTF8.c_str(), htons( port ), txtLen, txtRecord, ( DNSServiceRegisterReply ) &RegisterReply, object ); 599 600 require_noerr( err, exit ); 601 602 603 604 object->SetPrimaryRef( m_primary ); 605 606 object->SetSubordRef( subord ); 607 608 object->SetEventManager( eventManager ); 609 610 611 612 *service = object; 613 614 615 616exit: 617 618 619 620 if ( err && object ) 621 622 { 623 624 object->Release(); 625 626 } 627 628 629 630 return err; 631 632} 633 634 635 636 637 638STDMETHODIMP CDNSSDService::QueryRecord(DNSSDFlags flags, ULONG ifIndex, BSTR fullname, DNSSDRRType rrtype, DNSSDRRClass rrclass, IDNSSDEventManager *eventManager, IDNSSDService **service) 639 640{ 641 642 CComObject<CDNSSDService> * object = NULL; 643 644 DNSServiceRef subord = NULL; 645 646 std::string fullNameUTF8; 647 648 DNSServiceErrorType err = 0; 649 650 HRESULT hr = 0; 651 652 BOOL ok; 653 654 655 656 check( m_primary ); 657 658 659 660 // Initialize 661 662 *service = NULL; 663 664 665 666 // Convert BSTR params to utf8 667 668 ok = BSTRToUTF8( fullname, fullNameUTF8 ); 669 670 require_action( ok, exit, err = kDNSServiceErr_BadParam ); 671 672 673 674 try 675 676 { 677 678 object = new CComObject<CDNSSDService>(); 679 680 } 681 682 catch ( ... ) 683 684 { 685 686 object = NULL; 687 688 } 689 690 691 692 require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory ); 693 694 object->AddRef(); 695 696 697 698 subord = m_primary; 699 700 err = DNSServiceQueryRecord( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, fullNameUTF8.c_str(), ( uint16_t ) rrtype, ( uint16_t ) rrclass, ( DNSServiceQueryRecordReply ) &QueryRecordReply, object ); 701 702 require_noerr( err, exit ); 703 704 705 706 object->SetPrimaryRef( m_primary ); 707 708 object->SetSubordRef( subord ); 709 710 object->SetEventManager( eventManager ); 711 712 713 714 *service = object; 715 716 717 718exit: 719 720 721 722 if ( err && object ) 723 724 { 725 726 object->Release(); 727 728 } 729 730 731 732 return err; 733 734} 735 736 737 738 739 740STDMETHODIMP CDNSSDService::RegisterRecord(DNSSDFlags flags, ULONG ifIndex, BSTR fullName, DNSSDRRType rrtype, DNSSDRRClass rrclass, VARIANT rdata, ULONG ttl, IDNSSDEventManager* eventManager, IDNSSDRecord** record) 741 742{ 743 744 CComObject<CDNSSDRecord> * object = NULL; 745 746 DNSRecordRef rref = NULL; 747 748 std::string fullNameUTF8; 749 750 std::vector< BYTE > byteArray; 751 752 const void * byteArrayPtr = NULL; 753 754 DNSServiceErrorType err = 0; 755 756 HRESULT hr = 0; 757 758 BOOL ok; 759 760 761 762 check( m_primary ); 763 764 765 766 // Initialize 767 768 *object = NULL; 769 770 771 772 // Convert BSTR params to utf8 773 774 ok = BSTRToUTF8( fullName, fullNameUTF8 ); 775 776 require_action( ok, exit, err = kDNSServiceErr_BadParam ); 777 778 779 780 // Convert the VARIANT 781 782 ok = VariantToByteArray( &rdata, byteArray ); 783 784 require_action( ok, exit, err = kDNSServiceErr_Unknown ); 785 786 787 788 try 789 790 { 791 792 object = new CComObject<CDNSSDRecord>(); 793 794 } 795 796 catch ( ... ) 797 798 { 799 800 object = NULL; 801 802 } 803 804 805 806 require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory ); 807 808 object->AddRef(); 809 810 811 812 err = DNSServiceRegisterRecord( m_primary, &rref, flags, ifIndex, fullNameUTF8.c_str(), rrtype, rrclass, ( uint16_t ) byteArray.size(), byteArray.size() > 0 ? &byteArray[ 0 ] : NULL, ttl, &RegisterRecordReply, object ); 813 814 require_noerr( err, exit ); 815 816 817 818 object->SetServiceObject( this ); 819 820 object->SetRecordRef( rref ); 821 822 this->SetEventManager( eventManager ); 823 824 825 826 *record = object; 827 828 829 830exit: 831 832 833 834 if ( err && object ) 835 836 { 837 838 object->Release(); 839 840 } 841 842 843 844 return err; 845 846} 847 848 849 850 851 852STDMETHODIMP CDNSSDService::AddRecord(DNSSDFlags flags, DNSSDRRType rrtype, VARIANT rdata, ULONG ttl, IDNSSDRecord ** record) 853 854{ 855 856 CComObject<CDNSSDRecord> * object = NULL; 857 858 DNSRecordRef rref = NULL; 859 860 std::vector< BYTE > byteArray; 861 862 const void * byteArrayPtr = NULL; 863 864 DNSServiceErrorType err = 0; 865 866 HRESULT hr = 0; 867 868 BOOL ok; 869 870 871 872 check( m_primary ); 873 874 875 876 // Initialize 877 878 *object = NULL; 879 880 881 882 // Convert the VARIANT 883 884 ok = VariantToByteArray( &rdata, byteArray ); 885 886 require_action( ok, exit, err = kDNSServiceErr_Unknown ); 887 888 889 890 try 891 892 { 893 894 object = new CComObject<CDNSSDRecord>(); 895 896 } 897 898 catch ( ... ) 899 900 { 901 902 object = NULL; 903 904 } 905 906 907 908 require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory ); 909 910 object->AddRef(); 911 912 913 914 err = DNSServiceAddRecord( m_primary, &rref, flags, rrtype, ( uint16_t ) byteArray.size(), byteArray.size() > 0 ? &byteArray[ 0 ] : NULL, ttl ); 915 916 require_noerr( err, exit ); 917 918 919 920 object->SetServiceObject( this ); 921 922 object->SetRecordRef( rref ); 923 924 925 926 *record = object; 927 928 929 930exit: 931 932 933 934 if ( err && object ) 935 936 { 937 938 object->Release(); 939 940 } 941 942 943 944 return err; 945 946} 947 948 949 950STDMETHODIMP CDNSSDService::ReconfirmRecord(DNSSDFlags flags, ULONG ifIndex, BSTR fullName, DNSSDRRType rrtype, DNSSDRRClass rrclass, VARIANT rdata) 951 952{ 953 954 std::string fullNameUTF8; 955 956 std::vector< BYTE > byteArray; 957 958 const void * byteArrayPtr = NULL; 959 960 DNSServiceErrorType err = 0; 961 962 HRESULT hr = 0; 963 964 BOOL ok; 965 966 967 968 // Convert BSTR params to utf8 969 970 ok = BSTRToUTF8( fullName, fullNameUTF8 ); 971 972 require_action( ok, exit, err = kDNSServiceErr_BadParam ); 973 974 975 976 // Convert the VARIANT 977 978 ok = VariantToByteArray( &rdata, byteArray ); 979 980 require_action( ok, exit, err = kDNSServiceErr_Unknown ); 981 982 983 984 err = DNSServiceReconfirmRecord( flags, ifIndex, fullNameUTF8.c_str(), rrtype, rrclass, ( uint16_t ) byteArray.size(), byteArray.size() > 0 ? &byteArray[ 0 ] : NULL ); 985 986 require_noerr( err, exit ); 987 988 989 990exit: 991 992 993 994 return err; 995 996} 997 998 999 1000 1001 1002STDMETHODIMP CDNSSDService::GetProperty(BSTR prop, VARIANT * value ) 1003 1004{ 1005 1006 std::string propUTF8; 1007 1008 std::vector< BYTE > byteArray; 1009 1010 SAFEARRAY * psa = NULL; 1011 1012 BYTE * pData = NULL; 1013 1014 uint32_t elems = 0; 1015 1016 DNSServiceErrorType err = 0; 1017 1018 BOOL ok = TRUE; 1019 1020 1021 1022 // Convert BSTR params to utf8 1023 1024 ok = BSTRToUTF8( prop, propUTF8 ); 1025 1026 require_action( ok, exit, err = kDNSServiceErr_BadParam ); 1027 1028 1029 1030 // Setup the byte array 1031 1032 require_action( V_VT( value ) == ( VT_ARRAY|VT_UI1 ), exit, err = kDNSServiceErr_Unknown ); 1033 1034 psa = V_ARRAY( value ); 1035 1036 require_action( psa, exit, err = kDNSServiceErr_Unknown ); 1037 1038 require_action( SafeArrayGetDim( psa ) == 1, exit, err = kDNSServiceErr_Unknown ); 1039 1040 byteArray.reserve( psa->rgsabound[0].cElements ); 1041 1042 byteArray.assign( byteArray.capacity(), 0 ); 1043 1044 elems = ( uint32_t ) byteArray.capacity(); 1045 1046 1047 1048 // Call the function and package the return value in the Variant 1049 1050 err = DNSServiceGetProperty( propUTF8.c_str(), &byteArray[ 0 ], &elems ); 1051 1052 require_noerr( err, exit ); 1053 1054 ok = ByteArrayToVariant( &byteArray[ 0 ], elems, value ); 1055 1056 require_action( ok, exit, err = kDNSSDError_Unknown ); 1057 1058 1059 1060exit: 1061 1062 1063 1064 if ( psa ) 1065 1066 { 1067 1068 SafeArrayUnaccessData( psa ); 1069 1070 psa = NULL; 1071 1072 } 1073 1074 1075 1076 return err; 1077 1078} 1079 1080 1081 1082STDMETHODIMP CDNSSDService::GetAddrInfo(DNSSDFlags flags, ULONG ifIndex, DNSSDAddressFamily addressFamily, BSTR hostName, IDNSSDEventManager *eventManager, IDNSSDService **service) 1083 1084{ 1085 1086 CComObject<CDNSSDService> * object = NULL; 1087 1088 DNSServiceRef subord = NULL; 1089 1090 std::string hostNameUTF8; 1091 1092 DNSServiceErrorType err = 0; 1093 1094 HRESULT hr = 0; 1095 1096 BOOL ok; 1097 1098 1099 1100 check( m_primary ); 1101 1102 1103 1104 // Initialize 1105 1106 *service = NULL; 1107 1108 1109 1110 // Convert BSTR params to utf8 1111 1112 ok = BSTRToUTF8( hostName, hostNameUTF8 ); 1113 1114 require_action( ok, exit, err = kDNSServiceErr_BadParam ); 1115 1116 1117 1118 try 1119 1120 { 1121 1122 object = new CComObject<CDNSSDService>(); 1123 1124 } 1125 1126 catch ( ... ) 1127 1128 { 1129 1130 object = NULL; 1131 1132 } 1133 1134 1135 1136 require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory ); 1137 1138 object->AddRef(); 1139 1140 1141 1142 subord = m_primary; 1143 1144 err = DNSServiceGetAddrInfo( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, addressFamily, hostNameUTF8.c_str(), ( DNSServiceGetAddrInfoReply ) &GetAddrInfoReply, object ); 1145 1146 require_noerr( err, exit ); 1147 1148 1149 1150 object->SetPrimaryRef( m_primary ); 1151 1152 object->SetSubordRef( subord ); 1153 1154 object->SetEventManager( eventManager ); 1155 1156 1157 1158 *service = object; 1159 1160 1161 1162exit: 1163 1164 1165 1166 if ( err && object ) 1167 1168 { 1169 1170 object->Release(); 1171 1172 } 1173 1174 1175 1176 return err; 1177 1178} 1179 1180 1181 1182 1183 1184STDMETHODIMP CDNSSDService::NATPortMappingCreate(DNSSDFlags flags, ULONG ifIndex, DNSSDAddressFamily addressFamily, DNSSDProtocol protocol, USHORT internalPort, USHORT externalPort, ULONG ttl, IDNSSDEventManager *eventManager, IDNSSDService **service) 1185 1186{ 1187 1188 CComObject<CDNSSDService> * object = NULL; 1189 1190 DNSServiceRef subord = NULL; 1191 1192 DNSServiceProtocol prot = 0; 1193 1194 DNSServiceErrorType err = 0; 1195 1196 HRESULT hr = 0; 1197 1198 1199 1200 check( m_primary ); 1201 1202 1203 1204 // Initialize 1205 1206 *service = NULL; 1207 1208 1209 1210 try 1211 1212 { 1213 1214 object = new CComObject<CDNSSDService>(); 1215 1216 } 1217 1218 catch ( ... ) 1219 1220 { 1221 1222 object = NULL; 1223 1224 } 1225 1226 1227 1228 require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory ); 1229 1230 object->AddRef(); 1231 1232 1233 1234 prot = ( addressFamily | protocol ); 1235 1236 1237 1238 subord = m_primary; 1239 1240 err = DNSServiceNATPortMappingCreate( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, prot, htons( internalPort ), htons( externalPort ), ttl, ( DNSServiceNATPortMappingReply ) &NATPortMappingReply, object ); 1241 1242 require_noerr( err, exit ); 1243 1244 1245 1246 object->SetPrimaryRef( m_primary ); 1247 1248 object->SetSubordRef( subord ); 1249 1250 object->SetEventManager( eventManager ); 1251 1252 1253 1254 *service = object; 1255 1256 1257 1258exit: 1259 1260 1261 1262 if ( err && object ) 1263 1264 { 1265 1266 object->Release(); 1267 1268 } 1269 1270 1271 1272 return err; 1273 1274} 1275 1276 1277 1278 1279 1280STDMETHODIMP CDNSSDService::Stop(void) 1281 1282{ 1283 1284 if ( !m_stopped ) 1285 1286 { 1287 1288 m_stopped = TRUE; 1289 1290 1291 1292 dlog( kDebugLevelTrace, "Stop()\n" ); 1293 1294 1295 1296 if ( m_isPrimary && m_primary ) 1297 1298 { 1299 1300 SocketMap::iterator it; 1301 1302 1303 1304 if ( m_hiddenWindow ) 1305 1306 { 1307 1308 WSAAsyncSelect( DNSServiceRefSockFD( m_primary ), m_hiddenWindow, 0, 0 ); 1309 1310 } 1311 1312 1313 1314 it = m_socketMap.find( DNSServiceRefSockFD( m_primary ) ); 1315 1316 1317 1318 if ( it != m_socketMap.end() ) 1319 1320 { 1321 1322 m_socketMap.erase( it ); 1323 1324 } 1325 1326 1327 1328 DNSServiceRefDeallocate( m_primary ); 1329 1330 m_primary = NULL; 1331 1332 } 1333 1334 else if ( m_subord ) 1335 1336 { 1337 1338 DNSServiceRefDeallocate( m_subord ); 1339 1340 m_subord = NULL; 1341 1342 } 1343 1344 1345 1346 if ( m_eventManager != NULL ) 1347 1348 { 1349 1350 m_eventManager->Release(); 1351 1352 m_eventManager = NULL; 1353 1354 } 1355 1356 } 1357 1358 1359 1360 return S_OK; 1361 1362} 1363 1364 1365 1366 1367 1368void DNSSD_API 1369CDNSSDService::DomainEnumReply 1370 ( 1371 DNSServiceRef sdRef, 1372 DNSServiceFlags flags, 1373 uint32_t ifIndex, 1374 DNSServiceErrorType errorCode, 1375 const char *replyDomainUTF8, 1376 void *context 1377 ) 1378 1379{ 1380 1381 CComObject<CDNSSDService> * service = NULL; 1382 1383 CDNSSDEventManager * eventManager = NULL; 1384 1385 int err = 0; 1386 1387 1388 1389 service = ( CComObject< CDNSSDService>* ) context; 1390 1391 require_action( service, exit, err = kDNSServiceErr_Unknown ); 1392 1393 1394 1395 if ( service->ShouldHandleReply( errorCode, eventManager ) ) 1396 1397 { 1398 1399 CComBSTR replyDomain; 1400 1401 BOOL ok; 1402 1403 1404 1405 ok = UTF8ToBSTR( replyDomainUTF8, replyDomain ); 1406 1407 require_action( ok, exit, err = kDNSServiceErr_Unknown ); 1408 1409 1410 1411 if ( flags & kDNSServiceFlagsAdd ) 1412 1413 { 1414 1415 eventManager->Fire_DomainFound( service, ( DNSSDFlags ) flags, ifIndex, replyDomain ); 1416 1417 } 1418 1419 else 1420 1421 { 1422 1423 eventManager->Fire_DomainLost( service, ( DNSSDFlags ) flags, ifIndex, replyDomain ); 1424 1425 } 1426 1427 } 1428 1429 1430 1431exit: 1432 1433 1434 1435 return; 1436 1437} 1438 1439 1440 1441 1442 1443void DNSSD_API 1444CDNSSDService::BrowseReply 1445 ( 1446 DNSServiceRef sdRef, 1447 DNSServiceFlags flags, 1448 uint32_t ifIndex, 1449 DNSServiceErrorType errorCode, 1450 const char *serviceNameUTF8, 1451 const char *regTypeUTF8, 1452 const char *replyDomainUTF8, 1453 void *context 1454 ) 1455 1456{ 1457 1458 CComObject<CDNSSDService> * service = NULL; 1459 1460 CDNSSDEventManager * eventManager = NULL; 1461 1462 int err = 0; 1463 1464 1465 1466 service = ( CComObject< CDNSSDService>* ) context; 1467 1468 require_action( service, exit, err = kDNSServiceErr_Unknown ); 1469 1470 1471 1472 if ( service->ShouldHandleReply( errorCode, eventManager ) ) 1473 1474 { 1475 1476 CComBSTR serviceName; 1477 1478 CComBSTR regType; 1479 1480 CComBSTR replyDomain; 1481 1482 1483 1484 UTF8ToBSTR( serviceNameUTF8, serviceName ); 1485 1486 UTF8ToBSTR( regTypeUTF8, regType ); 1487 1488 UTF8ToBSTR( replyDomainUTF8, replyDomain ); 1489 1490 1491 1492 if ( flags & kDNSServiceFlagsAdd ) 1493 1494 { 1495 1496 eventManager->Fire_ServiceFound( service, ( DNSSDFlags ) flags, ifIndex, serviceName, regType, replyDomain ); 1497 1498 } 1499 1500 else 1501 1502 { 1503 1504 eventManager->Fire_ServiceLost( service, ( DNSSDFlags ) flags, ifIndex, serviceName, regType, replyDomain ); 1505 1506 } 1507 1508 } 1509 1510 1511 1512exit: 1513 1514 1515 1516 return; 1517 1518} 1519 1520 1521 1522 1523 1524void DNSSD_API 1525 1526CDNSSDService::ResolveReply 1527 1528 ( 1529 DNSServiceRef sdRef, 1530 DNSServiceFlags flags, 1531 uint32_t ifIndex, 1532 DNSServiceErrorType errorCode, 1533 const char *fullNameUTF8, 1534 const char *hostNameUTF8, 1535 uint16_t port, 1536 uint16_t txtLen, 1537 const unsigned char *txtRecord, 1538 void *context 1539 1540 ) 1541 1542{ 1543 1544 CComObject<CDNSSDService> * service = NULL; 1545 1546 CDNSSDEventManager * eventManager = NULL; 1547 1548 int err = 0; 1549 1550 1551 1552 service = ( CComObject< CDNSSDService>* ) context; 1553 1554 require_action( service, exit, err = kDNSServiceErr_Unknown ); 1555 1556 1557 1558 if ( service->ShouldHandleReply( errorCode, eventManager ) ) 1559 1560 { 1561 1562 CComBSTR fullName; 1563 1564 CComBSTR hostName; 1565 1566 CComBSTR regType; 1567 1568 CComBSTR replyDomain; 1569 1570 CComObject< CTXTRecord >* record; 1571 1572 BOOL ok; 1573 1574 1575 1576 ok = UTF8ToBSTR( fullNameUTF8, fullName ); 1577 1578 require_action( ok, exit, err = kDNSServiceErr_Unknown ); 1579 1580 ok = UTF8ToBSTR( hostNameUTF8, hostName ); 1581 1582 require_action( ok, exit, err = kDNSServiceErr_Unknown ); 1583 1584 1585 1586 try 1587 1588 { 1589 1590 record = new CComObject<CTXTRecord>(); 1591 1592 } 1593 1594 catch ( ... ) 1595 1596 { 1597 1598 record = NULL; 1599 1600 } 1601 1602 1603 1604 require_action( record, exit, err = kDNSServiceErr_NoMemory ); 1605 1606 record->AddRef(); 1607 1608 1609 1610 if ( txtLen > 0 ) 1611 1612 { 1613 1614 record->SetBytes( txtRecord, txtLen ); 1615 1616 } 1617 1618 1619 1620 eventManager->Fire_ServiceResolved( service, ( DNSSDFlags ) flags, ifIndex, fullName, hostName, ntohs( port ), record ); 1621 1622 } 1623 1624 1625 1626exit: 1627 1628 1629 1630 return; 1631 1632} 1633 1634 1635 1636 1637 1638void DNSSD_API 1639CDNSSDService::RegisterReply 1640 ( 1641 DNSServiceRef sdRef, 1642 DNSServiceFlags flags, 1643 DNSServiceErrorType errorCode, 1644 const char *serviceNameUTF8, 1645 const char *regTypeUTF8, 1646 const char *domainUTF8, 1647 void *context 1648 ) 1649 1650{ 1651 1652 CComObject<CDNSSDService> * service = NULL; 1653 1654 CDNSSDEventManager * eventManager = NULL; 1655 1656 int err = 0; 1657 1658 1659 1660 service = ( CComObject< CDNSSDService>* ) context; 1661 1662 require_action( service, exit, err = kDNSServiceErr_Unknown ); 1663 1664 1665 1666 if ( service->ShouldHandleReply( errorCode, eventManager ) ) 1667 1668 { 1669 1670 CComBSTR serviceName; 1671 1672 CComBSTR regType; 1673 1674 CComBSTR domain; 1675 1676 BOOL ok; 1677 1678 1679 1680 ok = UTF8ToBSTR( serviceNameUTF8, serviceName ); 1681 1682 require_action( ok, exit, err = kDNSServiceErr_Unknown ); 1683 1684 ok = UTF8ToBSTR( regTypeUTF8, regType ); 1685 1686 require_action( ok, exit, err = kDNSServiceErr_Unknown ); 1687 1688 ok = UTF8ToBSTR( domainUTF8, domain ); 1689 1690 require_action( ok, exit, err = kDNSServiceErr_Unknown ); 1691 1692 1693 1694 eventManager->Fire_ServiceRegistered( service, ( DNSSDFlags ) flags, serviceName, regType, domain ); 1695 1696 } 1697 1698 1699 1700exit: 1701 1702 1703 1704 return; 1705 1706} 1707 1708 1709 1710 1711 1712void DNSSD_API 1713CDNSSDService::QueryRecordReply 1714 ( 1715 DNSServiceRef sdRef, 1716 DNSServiceFlags flags, 1717 uint32_t ifIndex, 1718 DNSServiceErrorType errorCode, 1719 const char *fullNameUTF8, 1720 uint16_t rrtype, 1721 uint16_t rrclass, 1722 uint16_t rdlen, 1723 const void *rdata, 1724 uint32_t ttl, 1725 void *context 1726 ) 1727 1728{ 1729 1730 CComObject<CDNSSDService> * service = NULL; 1731 1732 CDNSSDEventManager * eventManager = NULL; 1733 1734 int err = 0; 1735 1736 1737 1738 service = ( CComObject< CDNSSDService>* ) context; 1739 1740 require_action( service, exit, err = kDNSServiceErr_Unknown ); 1741 1742 1743 1744 if ( service->ShouldHandleReply( errorCode, eventManager ) ) 1745 1746 { 1747 1748 CComBSTR fullName; 1749 1750 VARIANT var; 1751 1752 BOOL ok; 1753 1754 1755 1756 ok = UTF8ToBSTR( fullNameUTF8, fullName ); 1757 1758 require_action( ok, exit, err = kDNSServiceErr_Unknown ); 1759 1760 ok = ByteArrayToVariant( rdata, rdlen, &var ); 1761 1762 require_action( ok, exit, err = kDNSServiceErr_Unknown ); 1763 1764 1765 1766 eventManager->Fire_QueryRecordAnswered( service, ( DNSSDFlags ) flags, ifIndex, fullName, ( DNSSDRRType ) rrtype, ( DNSSDRRClass ) rrclass, var, ttl ); 1767 1768 } 1769 1770 1771 1772exit: 1773 1774 1775 1776 return; 1777 1778} 1779 1780 1781 1782 1783 1784void DNSSD_API 1785CDNSSDService::GetAddrInfoReply 1786 ( 1787 DNSServiceRef sdRef, 1788 DNSServiceFlags flags, 1789 uint32_t ifIndex, 1790 DNSServiceErrorType errorCode, 1791 const char *hostNameUTF8, 1792 const struct sockaddr *rawAddress, 1793 uint32_t ttl, 1794 void *context 1795 ) 1796 1797{ 1798 1799 CComObject<CDNSSDService> * service = NULL; 1800 1801 CDNSSDEventManager * eventManager = NULL; 1802 1803 int err = 0; 1804 1805 1806 1807 service = ( CComObject< CDNSSDService>* ) context; 1808 1809 require_action( service, exit, err = kDNSServiceErr_Unknown ); 1810 1811 1812 1813 if ( service->ShouldHandleReply( errorCode, eventManager ) ) 1814 1815 { 1816 1817 CComBSTR hostName; 1818 1819 DWORD sockaddrLen; 1820 1821 DNSSDAddressFamily addressFamily; 1822 1823 char addressUTF8[INET6_ADDRSTRLEN]; 1824 1825 DWORD addressLen = sizeof( addressUTF8 ); 1826 1827 CComBSTR address; 1828 1829 BOOL ok; 1830 1831 1832 1833 ok = UTF8ToBSTR( hostNameUTF8, hostName ); 1834 1835 require_action( ok, exit, err = kDNSServiceErr_Unknown ); 1836 1837 1838 1839 switch ( rawAddress->sa_family ) 1840 1841 { 1842 1843 case AF_INET: 1844 1845 { 1846 1847 addressFamily = kDNSSDAddressFamily_IPv4; 1848 1849 sockaddrLen = sizeof( sockaddr_in ); 1850 1851 } 1852 1853 break; 1854 1855 1856 1857 case AF_INET6: 1858 1859 { 1860 1861 addressFamily = kDNSSDAddressFamily_IPv6; 1862 1863 sockaddrLen = sizeof( sockaddr_in6 ); 1864 1865 } 1866 1867 break; 1868 1869 } 1870 1871 1872 1873 err = WSAAddressToStringA( ( LPSOCKADDR ) rawAddress, sockaddrLen, NULL, addressUTF8, &addressLen ); 1874 1875 require_noerr( err, exit ); 1876 1877 ok = UTF8ToBSTR( addressUTF8, address ); 1878 1879 require_action( ok, exit, err = kDNSServiceErr_Unknown ); 1880 1881 1882 1883 eventManager->Fire_AddressFound( service, ( DNSSDFlags ) flags, ifIndex, hostName, addressFamily, address, ttl ); 1884 1885 } 1886 1887 1888 1889exit: 1890 1891 1892 1893 return; 1894 1895} 1896 1897 1898 1899 1900 1901void DNSSD_API 1902CDNSSDService::NATPortMappingReply 1903 ( 1904 DNSServiceRef sdRef, 1905 DNSServiceFlags flags, 1906 uint32_t ifIndex, 1907 DNSServiceErrorType errorCode, 1908 uint32_t externalAddress, /* four byte IPv4 address in network byte order */ 1909 DNSServiceProtocol protocol, 1910 uint16_t internalPort, 1911 uint16_t externalPort, /* may be different than the requested port */ 1912 uint32_t ttl, /* may be different than the requested ttl */ 1913 void *context 1914 ) 1915 1916{ 1917 1918 CComObject<CDNSSDService> * service = NULL; 1919 1920 CDNSSDEventManager * eventManager = NULL; 1921 1922 int err = 0; 1923 1924 1925 1926 service = ( CComObject< CDNSSDService>* ) context; 1927 1928 require_action( service, exit, err = kDNSServiceErr_Unknown ); 1929 1930 1931 1932 if ( service->ShouldHandleReply( errorCode, eventManager ) ) 1933 1934 { 1935 1936 eventManager->Fire_MappingCreated( service, ( DNSSDFlags ) flags, ifIndex, externalAddress, ( DNSSDAddressFamily ) ( protocol & 0x8 ), ( DNSSDProtocol ) ( protocol & 0x80 ), ntohs( internalPort ), ntohs( externalPort ), ttl ); 1937 1938 } 1939 1940 1941 1942exit: 1943 1944 1945 1946 return; 1947 1948} 1949 1950 1951 1952 1953 1954void DNSSD_API 1955CDNSSDService::RegisterRecordReply 1956 ( 1957 DNSServiceRef sdRef, 1958 DNSRecordRef RecordRef, 1959 DNSServiceFlags flags, 1960 DNSServiceErrorType errorCode, 1961 void *context 1962 ) 1963 1964{ 1965 1966 CComObject<CDNSSDRecord> * record = NULL; 1967 1968 CDNSSDService * service = NULL; 1969 1970 CDNSSDEventManager * eventManager = NULL; 1971 1972 int err = 0; 1973 1974 1975 1976 record = ( CComObject< CDNSSDRecord >* ) context; 1977 1978 require_action( record, exit, err = kDNSServiceErr_Unknown ); 1979 1980 service = record->GetServiceObject(); 1981 1982 require_action( service, exit, err = kDNSServiceErr_Unknown ); 1983 1984 1985 1986 if ( service->ShouldHandleReply( errorCode, eventManager ) ) 1987 1988 { 1989 1990 eventManager->Fire_RecordRegistered( record, ( DNSSDFlags ) flags ); 1991 1992 } 1993 1994 1995 1996exit: 1997 1998 1999 2000 return; 2001 2002} 2003 2004 2005 2006 2007 2008BOOL 2009 2010CDNSSDService::ShouldHandleReply( DNSServiceErrorType errorCode, CDNSSDEventManager *& eventManager ) 2011 2012{ 2013 2014 BOOL ok = FALSE; 2015 2016 2017 2018 if ( !this->Stopped() ) 2019 2020 { 2021 2022 eventManager = this->GetEventManager(); 2023 2024 require_action( eventManager, exit, ok = FALSE ); 2025 2026 2027 2028 if ( !errorCode ) 2029 2030 { 2031 2032 ok = TRUE; 2033 2034 } 2035 2036 else 2037 2038 { 2039 2040 eventManager->Fire_OperationFailed( this, ( DNSSDError ) errorCode ); 2041 2042 } 2043 2044 } 2045 2046 2047 2048exit: 2049 2050 2051 2052 return ok; 2053 2054} 2055 2056 2057 2058 2059 2060LRESULT CALLBACK 2061 2062CDNSSDService::WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ) 2063 2064{ 2065 2066 if ( msg == WM_SOCKET ) 2067 2068 { 2069 2070 SocketMap::iterator it; 2071 2072 2073 2074 it = m_socketMap.find( ( SOCKET ) wParam ); 2075 2076 check( it != m_socketMap.end() ); 2077 2078 2079 2080 if ( it != m_socketMap.end() ) 2081 2082 { 2083 2084 DNSServiceProcessResult( it->second->m_primary ); 2085 2086 } 2087 2088 } 2089 2090 2091 2092 return DefWindowProc(hWnd, msg, wParam, lParam);; 2093 2094} 2095 2096