1 #include "precomp.h" 2 3 #include <stdlib.h> 4 #include <ws2spi.h> 5 #include <nspapi.h> 6 #include <windef.h> 7 #include <winuser.h> 8 #include <windns.h> 9 #include <guiddef.h> 10 #include <svcguid.h> 11 #include <iptypes.h> 12 #include <strsafe.h> 13 #include <winreg.h> 14 15 #include "mswhelper.h" 16 17 #define NDEBUG 18 #include <debug.h> 19 20 #define NSP_CALLID_DNS 0x0001 21 #define NSP_CALLID_HOSTNAME 0x0002 22 #define NSP_CALLID_HOSTBYNAME 0x0003 23 #define NSP_CALLID_SERVICEBYNAME 0x0004 24 25 #ifndef BUFSIZ 26 #define BUFSIZ 1024 27 #endif // BUFSIZ 28 #ifndef WS2_INTERNAL_MAX_ALIAS 29 #define WS2_INTERNAL_MAX_ALIAS 512 30 #endif // WS2_INTERNAL_MAX_ALIAS 31 32 //#define IP_LOCALHOST 0x0100007F 33 34 //#define NSP_REDIRECT 35 36 typedef struct { 37 WCHAR* hostnameW; 38 DWORD addr4; 39 WCHAR* servnameW; 40 WCHAR* servprotoW; 41 CHAR** servaliasesA; /* array */ 42 WORD servport; 43 } WSHOSTINFOINTERN, *PWSHOSTINFOINTERN; 44 45 typedef struct { 46 GUID providerId; /* Provider-ID */ 47 DWORD dwControlFlags; /* dwControlFlags (WSALookupServiceBegin) */ 48 DWORD CallID; /* List for LookupServiceNext-Calls */ 49 DWORD CallIDCounter; /* call-count of the current CallID. */ 50 WCHAR* hostnameW; /* hostbyname */ 51 #ifdef NSP_REDIRECT 52 HANDLE rdrLookup; 53 NSP_ROUTINE rdrproc; 54 #endif 55 } WSHANDLEINTERN, *PWSHANDLEINTERN; 56 57 static const GUID guid_NULL = {0}; 58 static const GUID guid_HOSTNAME = SVCID_HOSTNAME; 59 static const GUID guid_INET_HOSTADDRBYINETSTRING = SVCID_INET_HOSTADDRBYINETSTRING; 60 static const GUID guid_INET_HOSTADDRBYNAME = SVCID_INET_HOSTADDRBYNAME; 61 static const GUID guid_INET_SERVICEBYNAME = SVCID_INET_SERVICEBYNAME; 62 63 /* GUIDs - maybe they should be loaded from registry? */ 64 /* Namespace: 32 */ 65 static const GUID guid_mswsock_TcpIp = {/*Data1:*/ 0x22059D40, 66 /*Data2:*/ 0x7E9E, 67 /*Data3:*/ 0x11CF, 68 /*Data4:*/ {0xAE, 0x5A, 0x00, 0xAA, 0x00, 0xA7, 0x11, 0x2B}}; 69 70 /* {6642243A-3BA8-4AA6-BAA5-2E0BD71FDD83} */ 71 /* Namespace: 15 */ 72 static const GUID guid_mswsock_NLA = {/*Data1:*/ 0x6642243A, 73 /*Data2:*/ 0x3BA8, 74 /*Data3:*/ 0x4AA6, 75 /*Data4:*/ {0xBA, 0xA5, 0x2E, 0x0B, 0xD7, 0x1F, 0xDD, 0x83}}; 76 77 #ifdef NSP_REDIRECT 78 79 typedef INT 80 (CALLBACK *lpRdrNSPStartup)( 81 LPGUID lpProviderId, 82 LPNSP_ROUTINE lpRout); 83 84 const rdrLib = "mswsock.dll-original"; 85 lpRdrNSPStartup rdrNSPStartup; 86 HANDLE hLib; 87 NSP_ROUTINE rdrproc_tcpip; 88 NSP_ROUTINE rdrproc_nla; 89 90 #endif /* NSP_REDIRECT */ 91 92 /* Forwards */ 93 INT 94 WINAPI 95 mswNSPStartup( 96 LPGUID lpProviderId, 97 LPNSP_ROUTINE lpRout); 98 99 INT 100 NSP_LookupServiceBeginW( 101 PWSHANDLEINTERN data, 102 CHAR* hostnameA, 103 WCHAR* hostnameW, 104 DWORD CallID); 105 106 INT 107 NSP_LookupServiceNextW( 108 _In_ PWSHANDLEINTERN data, 109 _In_ DWORD dwControlFlags, 110 _Inout_ LPWSAQUERYSETW lpRes, 111 _Inout_ LPDWORD lpResLen); 112 113 INT 114 NSP_GetHostNameHeapAllocW( 115 _Out_ WCHAR** hostname); 116 117 INT 118 NSP_GetHostByNameHeapAllocW( 119 _In_ PWSHANDLEINTERN data, 120 _In_ DWORD dwControlFlags, 121 _Out_ PWSHOSTINFOINTERN hostinfo); 122 123 INT 124 NSP_GetServiceByNameHeapAllocW( 125 _In_ PWSHANDLEINTERN data, 126 _In_ DWORD dwControlFlags, 127 _Out_ PWSHOSTINFOINTERN hostinfo); 128 129 /* Implementations - Internal */ 130 131 INT 132 WSAAPI 133 mwsNSPCleanUp(_In_ LPGUID lpProviderId) 134 { 135 //WSASetLastError(ERROR_CALL_NOT_IMPLEMENTED); 136 //return ERROR_CALL_NOT_IMPLEMENTED; 137 return ERROR_SUCCESS; 138 } 139 140 INT 141 mwsNSPInit(VOID) 142 { 143 return ERROR_SUCCESS; 144 } 145 146 INT 147 WSAAPI 148 mwsNSPLookupServiceBegin(_In_ LPGUID lpProviderId, 149 _In_ LPWSAQUERYSETW lpqsRestrictions, 150 _In_ LPWSASERVICECLASSINFOW lpServiceClassInfo, 151 _In_ DWORD dwControlFlags, 152 _Out_ LPHANDLE lphLookup) 153 { 154 PWSHANDLEINTERN pLook; 155 int wsaErr; 156 157 if (IsEqualGUID(lpProviderId, &guid_mswsock_TcpIp)) 158 { 159 //OK 160 } 161 else if (IsEqualGUID(lpProviderId, &guid_mswsock_NLA)) 162 { 163 WSASetLastError(WSASERVICE_NOT_FOUND); 164 return SOCKET_ERROR; 165 } 166 else 167 { 168 return ERROR_CALL_NOT_IMPLEMENTED; 169 } 170 171 /* allocate internal structure */ 172 pLook = HeapAlloc(GetProcessHeap(), 0, sizeof(WSHANDLEINTERN)); 173 if (!pLook) 174 { 175 WSASetLastError(WSAEFAULT); 176 return SOCKET_ERROR; 177 } 178 179 *lphLookup = (HANDLE)pLook; 180 181 RtlZeroMemory(pLook, sizeof(*pLook)); 182 183 /* Anyway the ControlFlags "should" be needed 184 in NSPLookupServiceNext. (see doku) But 185 thats not the fact ATM. */ 186 pLook->dwControlFlags = dwControlFlags; 187 pLook->providerId = *lpProviderId; 188 189 #ifdef NSP_REDIRECT 190 191 if (IsEqualGUID(lpProviderId, &guid_mswsock_TcpIp)) 192 { 193 pLook->rdrproc = rdrproc_tcpip; 194 } 195 else if (IsEqualGUID(lpProviderId, &guid_mswsock_NLA)) 196 { 197 pLook->rdrproc = rdrproc_nla; 198 } 199 else 200 { 201 return ERROR_CALL_NOT_IMPLEMENTED; 202 } 203 204 if (pLook->rdrproc.NSPLookupServiceBegin(lpProviderId, 205 lpqsRestrictions, 206 lpServiceClassInfo, 207 dwControlFlags, 208 &pLook->rdrLookup) == NO_ERROR) 209 { 210 wsaErr = NO_ERROR; 211 } 212 else 213 { 214 wsaErr = WSAGetLastError(); 215 } 216 217 /* 218 if (res) 219 res = WSAGetLastError(); 220 */ 221 222 #else /* NSP_REDIRECT */ 223 224 wsaErr = ERROR_CALL_NOT_IMPLEMENTED; 225 if (IsEqualGUID(lpqsRestrictions->lpServiceClassId, &guid_NULL)) 226 { 227 wsaErr = ERROR_CALL_NOT_IMPLEMENTED; 228 } 229 else if (IsEqualGUID(lpqsRestrictions->lpServiceClassId, &guid_HOSTNAME)) 230 { 231 wsaErr = NSP_LookupServiceBeginW(pLook, 232 NULL, 233 NULL, 234 NSP_CALLID_HOSTNAME); 235 } 236 else if (IsEqualGUID(lpqsRestrictions->lpServiceClassId, 237 &guid_INET_HOSTADDRBYNAME)) 238 { 239 wsaErr = NSP_LookupServiceBeginW(pLook, 240 NULL, 241 lpqsRestrictions->lpszServiceInstanceName, 242 NSP_CALLID_HOSTBYNAME); 243 } 244 else if (IsEqualGUID(lpqsRestrictions->lpServiceClassId, 245 &guid_INET_SERVICEBYNAME)) 246 { 247 wsaErr = NSP_LookupServiceBeginW(pLook, 248 NULL, 249 lpqsRestrictions->lpszServiceInstanceName, 250 NSP_CALLID_SERVICEBYNAME); 251 } 252 else if (IsEqualGUID(lpqsRestrictions->lpServiceClassId, 253 &guid_INET_HOSTADDRBYINETSTRING)) 254 { 255 wsaErr = ERROR_CALL_NOT_IMPLEMENTED; 256 } 257 258 #endif /* NSP_REDIRECT */ 259 260 if (wsaErr != NO_ERROR) 261 { 262 WSASetLastError(wsaErr); 263 return SOCKET_ERROR; 264 } 265 return NO_ERROR; 266 } 267 268 INT 269 WSAAPI 270 mwsNSPLookupServiceNext(_In_ HANDLE hLookup, 271 _In_ DWORD dwControlFlags, 272 _Inout_ LPDWORD lpdwBufferLength, 273 //_Out_writes_bytes_to_(*lpdwBufferLength, *lpdwBufferLength) 274 LPWSAQUERYSETW lpqsResults) 275 { 276 PWSHANDLEINTERN pLook = hLookup; 277 int wsaErr = 0; 278 279 #ifdef NSP_REDIRECT 280 281 INT res = pLook->rdrproc.NSPLookupServiceNext(pLook->rdrLookup, 282 dwControlFlags, 283 lpdwBufferLength, 284 lpqsResults); 285 wsaErr = WSAGetLastError(); 286 if (res != ERROR_SUCCESS) 287 { 288 wsaErr = WSAGetLastError(); 289 290 if (wsaErr == 0) 291 wsaErr = 0xFFFFFFFF; 292 } 293 294 #else /* NSP_REDIRECT */ 295 296 if ((lpdwBufferLength == NULL) || (*lpdwBufferLength == 0)) 297 { 298 wsaErr = WSA_NOT_ENOUGH_MEMORY; 299 goto End; 300 } 301 302 RtlZeroMemory(lpqsResults, *lpdwBufferLength); 303 lpqsResults->dwSize = sizeof(*lpqsResults); 304 305 wsaErr = NSP_LookupServiceNextW(pLook, 306 dwControlFlags, 307 lpqsResults, 308 lpdwBufferLength); 309 310 311 #endif /* NSP_REDIRECT */ 312 313 End: 314 if (wsaErr != 0) 315 { 316 WSASetLastError(wsaErr); 317 return SOCKET_ERROR; 318 } 319 return NO_ERROR; 320 } 321 322 INT 323 WSAAPI 324 mwsNSPIoCtl(_In_ HANDLE hLookup, 325 _In_ DWORD dwControlCode, 326 _In_reads_bytes_(cbInBuffer) LPVOID lpvInBuffer, 327 _In_ DWORD cbInBuffer, 328 _Out_writes_bytes_to_(cbOutBuffer, *lpcbBytesReturned) LPVOID lpvOutBuffer, 329 _In_ DWORD cbOutBuffer, 330 _Out_ LPDWORD lpcbBytesReturned, 331 _In_opt_ LPWSACOMPLETION lpCompletion, 332 _In_ LPWSATHREADID lpThreadId) 333 { 334 WSASetLastError(ERROR_CALL_NOT_IMPLEMENTED); 335 return ERROR_CALL_NOT_IMPLEMENTED; 336 } 337 338 INT 339 WSAAPI 340 mwsNSPLookupServiceEnd(_In_ HANDLE hLookup) 341 { 342 PWSHANDLEINTERN pLook; 343 HANDLE hHeap; 344 INT res; 345 346 res = NO_ERROR; 347 pLook = (PWSHANDLEINTERN)hLookup; 348 hHeap = GetProcessHeap(); 349 350 #ifdef NSP_REDIRECT 351 res = pLook->rdrproc.NSPLookupServiceEnd(pLook->rdrLookup); 352 #endif 353 354 if (pLook->hostnameW != NULL) 355 HeapFree(hHeap, 0, pLook->hostnameW); 356 357 HeapFree(hHeap, 0, pLook); 358 return res; 359 } 360 361 INT 362 WSAAPI 363 mwsNSPSetService(_In_ LPGUID lpProviderId, 364 _In_ LPWSASERVICECLASSINFOW lpServiceClassInfo, 365 _In_ LPWSAQUERYSETW lpqsRegInfo, 366 _In_ WSAESETSERVICEOP essOperation, 367 _In_ DWORD dwControlFlags) 368 { 369 WSASetLastError(ERROR_CALL_NOT_IMPLEMENTED); 370 return ERROR_CALL_NOT_IMPLEMENTED; 371 } 372 373 INT 374 WSAAPI 375 mwsNSPInstallServiceClass(_In_ LPGUID lpProviderId, 376 _In_ LPWSASERVICECLASSINFOW lpServiceClassInfo) 377 { 378 WSASetLastError(ERROR_CALL_NOT_IMPLEMENTED); 379 return ERROR_CALL_NOT_IMPLEMENTED; 380 } 381 382 INT 383 WSAAPI 384 mwsNSPRemoveServiceClass(_In_ LPGUID lpProviderId, 385 _In_ LPGUID lpServiceClassId) 386 { 387 WSASetLastError(ERROR_CALL_NOT_IMPLEMENTED); 388 return ERROR_CALL_NOT_IMPLEMENTED; 389 } 390 391 INT 392 WSAAPI 393 mwsNSPGetServiceClassInfo(_In_ LPGUID lpProviderId, 394 _In_ LPDWORD lpdwBufSize, 395 _In_ LPWSASERVICECLASSINFOW lpServiceClassInfo) 396 { 397 WSASetLastError(ERROR_CALL_NOT_IMPLEMENTED); 398 return ERROR_CALL_NOT_IMPLEMENTED; 399 } 400 401 /* 402 hostnameA / hostnameW 403 * only used by HOSTBYNAME 404 * only one should be set 405 406 */ 407 INT 408 NSP_LookupServiceBeginW(PWSHANDLEINTERN data, 409 CHAR* hostnameA, 410 WCHAR* hostnameW, 411 DWORD CallID) 412 { 413 HANDLE hHeap; 414 415 if (data->CallID != 0) 416 return WSAEFAULT; 417 418 data->CallID = CallID; 419 420 if ((CallID == NSP_CALLID_HOSTBYNAME) || 421 (CallID == NSP_CALLID_SERVICEBYNAME)) 422 { 423 hHeap = GetProcessHeap(); 424 425 if (data->hostnameW != NULL) 426 HeapFree(hHeap, 0, data->hostnameW); 427 428 if (hostnameA != NULL) 429 { 430 data->hostnameW = StrA2WHeapAlloc(hHeap, hostnameA); 431 } 432 else 433 { 434 data->hostnameW = StrCpyHeapAllocW(hHeap, hostnameW); 435 } 436 } 437 438 WSASetLastError(0); 439 440 return ERROR_SUCCESS; 441 } 442 443 INT 444 NSP_GetHostNameHeapAllocW(_Out_ WCHAR** hostname) 445 { 446 WCHAR* name; 447 HANDLE hHeap = GetProcessHeap(); 448 DWORD bufCharLen = MAX_COMPUTERNAME_LENGTH + 1; 449 DWORD bufByteLen = bufCharLen * sizeof(WCHAR); 450 451 name = HeapAlloc(hHeap, 0, bufByteLen); 452 453 if (!GetComputerNameExW(ComputerNameDnsHostname, 454 name, 455 &bufCharLen)) 456 { 457 HeapFree(hHeap, 0, name); 458 WSASetLastError(WSAEFAULT); 459 return SOCKET_ERROR; 460 } 461 462 *hostname = name; 463 return ERROR_SUCCESS; 464 } 465 466 INT 467 NSP_GetHostByNameHeapAllocW(_In_ PWSHANDLEINTERN data, 468 _In_ DWORD dwControlFlags, 469 _Out_ PWSHOSTINFOINTERN hostinfo) 470 { 471 HANDLE hHeap = GetProcessHeap(); 472 DNS_STATUS dns_status = { 0 }; 473 /* include/WinDNS.h -- look up DNS_RECORD on MSDN */ 474 PDNS_RECORDW dp; 475 PDNS_RECORDW curr; 476 INT result = ERROR_SUCCESS; 477 DWORD dwQueryFlags = DNS_QUERY_STANDARD; 478 PWCHAR Aliases[WS2_INTERNAL_MAX_ALIAS] = { 0 }; 479 int AliasIndex = 0; 480 481 /* needed to be cleaned up if != NULL */ 482 dp = NULL; 483 484 if (data->hostnameW == NULL) 485 { 486 result = ERROR_INVALID_PARAMETER; 487 goto cleanup; 488 } 489 490 if ((data->dwControlFlags & LUP_DEEP) == 0) 491 { 492 dwQueryFlags |= DNS_QUERY_NO_RECURSION; 493 } 494 495 /* DNS_TYPE_A: include/WinDNS.h */ 496 /* DnsQuery -- lib/dnsapi/dnsapi/query.c */ 497 dns_status = DnsQuery_W(data->hostnameW, 498 DNS_TYPE_A, 499 dwQueryFlags, 500 NULL /* extra dns servers */, 501 &dp, 502 NULL); 503 if (dns_status == ERROR_INVALID_NAME) 504 { 505 WSASetLastError(WSAEFAULT); 506 result = ERROR_INVALID_PARAMETER; 507 goto cleanup; 508 } 509 510 if ((dns_status != 0) || (dp == NULL)) 511 { 512 result = WSAHOST_NOT_FOUND; 513 goto cleanup; 514 } 515 516 //ASSERT(dp->wType == DNS_TYPE_A); 517 //ASSERT(dp->wDataLength == sizeof(DNS_A_DATA)); 518 curr = dp; 519 while ((curr->pNext != NULL) || (curr->wType != DNS_TYPE_A)) 520 { 521 if (curr->wType == DNS_TYPE_CNAME) 522 { 523 Aliases[AliasIndex++] = curr->Data.Cname.pNameHost; 524 } 525 curr = curr->pNext; 526 } 527 528 if (curr->wType != DNS_TYPE_A) 529 { 530 result = WSASERVICE_NOT_FOUND; 531 goto cleanup; 532 } 533 hostinfo->hostnameW = StrCpyHeapAllocW(hHeap, curr->pName); 534 hostinfo->addr4 = curr->Data.A.IpAddress; 535 if (AliasIndex) 536 { 537 hostinfo->servaliasesA = StrAryCpyHeapAllocWToA(hHeap, (WCHAR**)&Aliases); 538 } 539 result = ERROR_SUCCESS; 540 541 cleanup: 542 if (dp != NULL) 543 DnsRecordListFree(dp, DnsFreeRecordList); 544 545 return result; 546 } 547 548 #define SKIPWS(ptr, act) \ 549 {while(*ptr && isspace(*ptr)) ptr++; if(!*ptr) act;} 550 551 #define SKIPANDMARKSTR(ptr, act) \ 552 {while(*ptr && !isspace(*ptr)) ptr++; \ 553 if(!*ptr) {act;} else { *ptr = 0; ptr++; }} 554 555 static 556 BOOL 557 DecodeServEntFromString(IN PCHAR ServiceString, 558 OUT PCHAR *ServiceName, 559 OUT PCHAR *PortNumberStr, 560 OUT PCHAR *ProtocolStr, 561 IN PCHAR *Aliases, 562 IN DWORD MaxAlias) 563 { 564 UINT NAliases = 0; 565 566 //WS_DbgPrint(MAX_TRACE, ("Parsing service ent [%s]\n", ServiceString)); 567 568 SKIPWS(ServiceString, return FALSE); 569 *ServiceName = ServiceString; 570 SKIPANDMARKSTR(ServiceString, return FALSE); 571 SKIPWS(ServiceString, return FALSE); 572 *PortNumberStr = ServiceString; 573 SKIPANDMARKSTR(ServiceString, ;); 574 575 while (*ServiceString && NAliases < MaxAlias - 1) 576 { 577 SKIPWS(ServiceString, break); 578 if (*ServiceString) 579 { 580 SKIPWS(ServiceString, ;); 581 if (strlen(ServiceString)) 582 { 583 //WS_DbgPrint(MAX_TRACE, ("Alias: %s\n", ServiceString)); 584 *Aliases++ = ServiceString; 585 NAliases++; 586 } 587 SKIPANDMARKSTR(ServiceString, ;); 588 } 589 } 590 *Aliases = NULL; 591 592 *ProtocolStr = strchr(*PortNumberStr, '/'); 593 594 if (!*ProtocolStr) 595 return FALSE; 596 597 **ProtocolStr = 0; 598 (*ProtocolStr)++; 599 600 //WS_DbgPrint(MAX_TRACE, ("Parsing done: %s %s %s %d\n", 601 // *ServiceName, *ProtocolStr, *PortNumberStr, 602 // NAliases)); 603 604 return TRUE; 605 } 606 607 HANDLE 608 WSAAPI 609 OpenNetworkDatabase(_In_ LPCWSTR Name) 610 { 611 PWSTR ExpandedPath; 612 PWSTR DatabasePath; 613 INT ErrorCode; 614 HKEY DatabaseKey; 615 DWORD RegType; 616 DWORD RegSize = 0; 617 size_t StringLength; 618 HANDLE ret; 619 620 ExpandedPath = HeapAlloc(GetProcessHeap(), 0, MAX_PATH*sizeof(WCHAR)); 621 if (!ExpandedPath) 622 return INVALID_HANDLE_VALUE; 623 624 /* Open the database path key */ 625 ErrorCode = RegOpenKeyEx(HKEY_LOCAL_MACHINE, 626 L"System\\CurrentControlSet\\Services\\Tcpip\\Parameters", 627 0, 628 KEY_READ, 629 &DatabaseKey); 630 if (ErrorCode == NO_ERROR) 631 { 632 /* Read the actual path */ 633 ErrorCode = RegQueryValueEx(DatabaseKey, 634 L"DatabasePath", 635 NULL, 636 &RegType, 637 NULL, 638 &RegSize); 639 640 DatabasePath = HeapAlloc(GetProcessHeap(), 0, RegSize); 641 if (!DatabasePath) 642 { 643 HeapFree(GetProcessHeap(), 0, ExpandedPath); 644 return INVALID_HANDLE_VALUE; 645 } 646 647 /* Read the actual path */ 648 ErrorCode = RegQueryValueEx(DatabaseKey, 649 L"DatabasePath", 650 NULL, 651 &RegType, 652 (LPBYTE)DatabasePath, 653 &RegSize); 654 655 /* Close the key */ 656 RegCloseKey(DatabaseKey); 657 658 /* Expand the name */ 659 ExpandEnvironmentStrings(DatabasePath, ExpandedPath, MAX_PATH); 660 661 HeapFree(GetProcessHeap(), 0, DatabasePath); 662 } 663 else 664 { 665 /* Use defalt path */ 666 GetSystemDirectory(ExpandedPath, MAX_PATH); 667 StringCchLength(ExpandedPath, MAX_PATH, &StringLength); 668 if (ExpandedPath[StringLength - 1] != L'\\') 669 { 670 /* It isn't, so add it ourselves */ 671 StringCchCat(ExpandedPath, MAX_PATH, L"\\"); 672 } 673 StringCchCat(ExpandedPath, MAX_PATH, L"DRIVERS\\ETC\\"); 674 } 675 676 /* Make sure that the path is backslash-terminated */ 677 StringCchLength(ExpandedPath, MAX_PATH, &StringLength); 678 if (ExpandedPath[StringLength - 1] != L'\\') 679 { 680 /* It isn't, so add it ourselves */ 681 StringCchCat(ExpandedPath, MAX_PATH, L"\\"); 682 } 683 684 /* Add the database name */ 685 StringCchCat(ExpandedPath, MAX_PATH, Name); 686 687 /* Return a handle to the file */ 688 ret = CreateFile(ExpandedPath, 689 FILE_READ_DATA, 690 FILE_SHARE_READ, 691 NULL, 692 OPEN_EXISTING, 693 FILE_ATTRIBUTE_NORMAL, 694 NULL); 695 696 HeapFree(GetProcessHeap(), 0, ExpandedPath); 697 return ret; 698 } 699 700 INT 701 NSP_GetServiceByNameHeapAllocW(_In_ PWSHANDLEINTERN data, 702 _In_ DWORD dwControlFlags, 703 _Out_ PWSHOSTINFOINTERN hostinfo) 704 { 705 BOOL Found = FALSE; 706 HANDLE ServicesFile; 707 CHAR ServiceDBData[BUFSIZ * sizeof(WCHAR)] = {0}; 708 PCHAR ThisLine = 0, NextLine = 0, ServiceName = 0, PortNumberStr = 0, 709 ProtocolStr = 0, Comment = 0, EndValid; 710 PCHAR Aliases[WS2_INTERNAL_MAX_ALIAS] = {0}; 711 PCHAR* AliasPtr; 712 UINT i = 0; 713 DWORD ReadSize = 0; 714 HANDLE hHeap; 715 PCHAR nameA = NULL; 716 PCHAR nameServiceA = NULL; 717 PCHAR nameProtoA = NULL; 718 INT res = WSANO_RECOVERY; 719 720 if (!data->hostnameW) 721 { 722 res = WSANO_RECOVERY; 723 goto End; 724 } 725 726 hHeap = GetProcessHeap(); 727 nameA = StrW2AHeapAlloc(hHeap, data->hostnameW); 728 729 /* nameA has the form <service-name>/<protocol> 730 we split these now */ 731 nameProtoA = strchr(nameA, '/'); 732 if (nameProtoA == NULL) 733 { 734 res = WSANO_RECOVERY; 735 goto End; 736 } 737 738 nameProtoA++; 739 i = (DWORD)(nameProtoA - nameA - 1); 740 nameServiceA = (PCHAR)HeapAlloc(hHeap, 0, i + 1); 741 StringCbCopyA(nameServiceA, i + 1, nameA); 742 nameServiceA[i] = '\0'; 743 744 ServicesFile = OpenNetworkDatabase(L"services"); 745 if (ServicesFile == INVALID_HANDLE_VALUE) 746 { 747 return WSANO_RECOVERY; 748 } 749 750 /* Scan the services file ... 751 * 752 * We will be share the buffer on the lines. If the line does not fit in 753 * the buffer, then moving it to the beginning of the buffer and read 754 * the remnants of line from file. 755 */ 756 757 /* Initial Read */ 758 ReadFile(ServicesFile, 759 ServiceDBData, 760 sizeof( ServiceDBData ) - 1, 761 &ReadSize, 762 NULL); 763 764 ThisLine = NextLine = ServiceDBData; 765 EndValid = ServiceDBData + ReadSize; 766 ServiceDBData[sizeof(ServiceDBData) - 1] = '\0'; 767 768 while (ReadSize) 769 { 770 for (; *NextLine != '\r' && *NextLine != '\n'; NextLine++) 771 { 772 if (NextLine == EndValid) 773 { 774 int LineLen = NextLine - ThisLine; 775 776 if (ThisLine == ServiceDBData) 777 { 778 //WS_DbgPrint(MIN_TRACE,("Line too long")); 779 return WSANO_RECOVERY; 780 } 781 782 memmove(ServiceDBData, ThisLine, LineLen); 783 784 ReadFile(ServicesFile, 785 ServiceDBData + LineLen, 786 sizeof( ServiceDBData )-1 - LineLen, 787 &ReadSize, 788 NULL); 789 790 EndValid = ServiceDBData + LineLen + ReadSize; 791 NextLine = ServiceDBData + LineLen; 792 ThisLine = ServiceDBData; 793 794 if (!ReadSize) break; 795 } 796 } 797 798 *NextLine = '\0'; 799 Comment = strchr(ThisLine, '#'); 800 801 if (Comment) 802 *Comment = '\0'; /* Terminate at comment start */ 803 804 if (DecodeServEntFromString(ThisLine, 805 &ServiceName, 806 &PortNumberStr, 807 &ProtocolStr, 808 Aliases, 809 WS2_INTERNAL_MAX_ALIAS) && 810 (strlen(nameProtoA) == 0 || strcmp(ProtocolStr, nameProtoA) == 0)) 811 { 812 Found = (strcmp(ServiceName, nameServiceA) == 0 || strcmp(PortNumberStr, nameServiceA) == 0); 813 AliasPtr = Aliases; 814 while ((!Found) && (*AliasPtr != NULL)) 815 { 816 Found = (strcmp(*AliasPtr, nameServiceA) == 0); 817 AliasPtr++; 818 } 819 if (Found) 820 break; 821 } 822 NextLine++; 823 ThisLine = NextLine; 824 } 825 826 /* This we'll do no matter what */ 827 CloseHandle(ServicesFile); 828 829 if (!Found) 830 { 831 return WSANO_DATA; 832 } 833 834 hostinfo->addr4 = 0; 835 hostinfo->servnameW = StrA2WHeapAlloc(hHeap, ServiceName); 836 hostinfo->servprotoW = StrA2WHeapAlloc(hHeap, ProtocolStr); 837 hostinfo->servaliasesA = StrAryCpyHeapAllocA(hHeap, (char**)&Aliases); 838 hostinfo->servport = atoi(PortNumberStr); 839 840 res = NO_ERROR; 841 842 End: 843 if (nameA != NULL) 844 HeapFree(hHeap, 0, nameA); 845 846 if (nameServiceA != NULL) 847 HeapFree(hHeap, 0, nameServiceA); 848 849 return res; 850 } 851 852 INT 853 NSP_LookupServiceNextW(_In_ PWSHANDLEINTERN data, 854 _In_ DWORD dwControlFlags, 855 _Inout_ LPWSAQUERYSETW lpRes, 856 _Inout_ LPDWORD lpResLen) 857 { 858 MSW_BUFFER buf; 859 WSHOSTINFOINTERN hostinfo; 860 INT result; 861 HANDLE hHeap = GetProcessHeap(); 862 WCHAR* ServiceInstanceNameW = NULL; 863 /* cleanup-vars */ 864 CHAR* ServiceInstanceNameA = NULL; 865 CHAR* ServiceProtocolNameA = NULL; 866 867 RtlZeroMemory(&hostinfo, sizeof(hostinfo)); 868 869 /* init and build result-buffer */ 870 mswBufferInit(&buf, (BYTE*)lpRes, *lpResLen); 871 mswBufferIncUsed(&buf, sizeof(*lpRes)); 872 873 /* QueryDataSet-Size without "blob-data"-size! */ 874 lpRes->dwSize = sizeof(*lpRes); 875 lpRes->dwNameSpace = NS_DNS; 876 877 if ((data->CallID == NSP_CALLID_HOSTNAME) || 878 (data->CallID == NSP_CALLID_HOSTBYNAME) || 879 (data->CallID == NSP_CALLID_SERVICEBYNAME)) 880 { 881 if (data->CallIDCounter >= 1) 882 { 883 result = WSAENOMORE; 884 goto End; 885 } 886 } 887 else 888 { 889 result = WSANO_RECOVERY; 890 goto End; 891 } 892 data->CallIDCounter++; 893 894 if (data->CallID == NSP_CALLID_HOSTNAME) 895 { 896 result = NSP_GetHostNameHeapAllocW(&hostinfo.hostnameW); 897 898 if (result != ERROR_SUCCESS) 899 goto End; 900 901 hostinfo.addr4 = 0; 902 } 903 else if (data->CallID == NSP_CALLID_HOSTBYNAME) 904 { 905 result = NSP_GetHostByNameHeapAllocW(data, 906 dwControlFlags, 907 &hostinfo); 908 if (result != ERROR_SUCCESS) 909 goto End; 910 } 911 else 912 { 913 ASSERT(data->CallID == NSP_CALLID_SERVICEBYNAME); 914 result = NSP_GetServiceByNameHeapAllocW(data, 915 dwControlFlags, 916 &hostinfo); 917 if (result != ERROR_SUCCESS) 918 goto End; 919 } 920 921 if (((LUP_RETURN_BLOB & data->dwControlFlags) != 0) || 922 ((LUP_RETURN_NAME & data->dwControlFlags) != 0)) 923 { 924 if (data->CallID == NSP_CALLID_HOSTNAME || data->CallID == NSP_CALLID_HOSTBYNAME) 925 { 926 ServiceInstanceNameW = hostinfo.hostnameW; 927 ServiceInstanceNameA = StrW2AHeapAlloc(hHeap, ServiceInstanceNameW); 928 if (ServiceInstanceNameA == NULL) 929 { 930 result = WSAEFAULT; 931 goto End; 932 933 } 934 } 935 if (data->CallID == NSP_CALLID_SERVICEBYNAME) 936 { 937 ServiceInstanceNameW = hostinfo.servnameW; 938 ServiceInstanceNameA = StrW2AHeapAlloc(hHeap, ServiceInstanceNameW); 939 if (ServiceInstanceNameA == NULL) 940 { 941 result = WSAEFAULT; 942 goto End; 943 944 } 945 ServiceProtocolNameA = StrW2AHeapAlloc(hHeap, hostinfo.servprotoW); 946 if (ServiceProtocolNameA == NULL) 947 { 948 result = WSAEFAULT; 949 goto End; 950 951 } 952 } 953 } 954 955 if ((LUP_RETURN_ADDR & data->dwControlFlags) != 0) 956 { 957 if (!mswBufferAppendAddr_AddrInfoW(&buf, lpRes, hostinfo.addr4)) 958 { 959 *lpResLen = buf.bytesUsed; 960 result = WSAEFAULT; 961 goto End; 962 } 963 } 964 965 if ((LUP_RETURN_BLOB & data->dwControlFlags) != 0) 966 { 967 if (data->CallID == NSP_CALLID_HOSTBYNAME) 968 { 969 /* Write data for PBLOB (hostent) */ 970 if (!mswBufferAppendBlob_Hostent(&buf, 971 lpRes, 972 (LUP_RETURN_ALIASES & data->dwControlFlags) != 0 ? hostinfo.servaliasesA : NULL, 973 ServiceInstanceNameA, 974 hostinfo.addr4)) 975 { 976 *lpResLen = buf.bytesUsed; 977 result = WSAEFAULT; 978 goto End; 979 } 980 } 981 else if (data->CallID == NSP_CALLID_SERVICEBYNAME) 982 { 983 /* Write data for PBLOB (servent) */ 984 if (!mswBufferAppendBlob_Servent(&buf, 985 lpRes, 986 ServiceInstanceNameA,/* ServiceName */ 987 (LUP_RETURN_ALIASES & data->dwControlFlags) != 0 ? hostinfo.servaliasesA : NULL, 988 ServiceProtocolNameA, 989 hostinfo.servport)) 990 { 991 *lpResLen = buf.bytesUsed; 992 result = WSAEFAULT; 993 goto End; 994 } 995 } 996 else 997 { 998 result = WSANO_RECOVERY; 999 goto End; 1000 } 1001 } 1002 1003 if ((LUP_RETURN_NAME & data->dwControlFlags) != 0) 1004 { 1005 /* HostByName sets the ServiceInstanceName to a 1006 (UNICODE)copy of hostent.h_name */ 1007 lpRes->lpszServiceInstanceName = (LPWSTR)mswBufferEndPtr(&buf); 1008 if (!mswBufferAppendStrW(&buf, ServiceInstanceNameW)) 1009 { 1010 lpRes->lpszServiceInstanceName = NULL; 1011 *lpResLen = buf.bytesUsed; 1012 result = WSAEFAULT; 1013 goto End; 1014 } 1015 } 1016 1017 *lpResLen = buf.bytesUsed; 1018 1019 result = ERROR_SUCCESS; 1020 End: 1021 /* cleanup */ 1022 if (ServiceInstanceNameA != NULL) 1023 HeapFree(hHeap, 0, ServiceInstanceNameA); 1024 1025 if (ServiceProtocolNameA != NULL) 1026 HeapFree(hHeap, 0, ServiceProtocolNameA); 1027 1028 if (hostinfo.hostnameW != NULL) 1029 HeapFree(hHeap, 0, hostinfo.hostnameW); 1030 1031 if (hostinfo.servnameW != NULL) 1032 HeapFree(hHeap, 0, hostinfo.servnameW); 1033 1034 if (hostinfo.servprotoW != NULL) 1035 HeapFree(hHeap, 0, hostinfo.servprotoW); 1036 1037 return result; 1038 } 1039 1040 /* Implementations - Exports */ 1041 /* 1042 * @implemented 1043 */ 1044 int 1045 WINAPI 1046 NSPStartup(_In_ LPGUID lpProviderId, 1047 _Out_ LPNSP_ROUTINE lpRout) 1048 { 1049 INT ret; 1050 1051 if ((lpRout == NULL) || 1052 (lpRout->cbSize != sizeof(NSP_ROUTINE))) 1053 { 1054 WSASetLastError(ERROR_INVALID_PARAMETER); 1055 return ERROR_INVALID_PARAMETER; 1056 } 1057 1058 mwsNSPInit(); 1059 1060 /* set own Provider GUID - maybe we need 1061 here to set the original mswsock-GUID?! */ 1062 1063 /* Win2k3 returns 1064 - Version 1.1 1065 - no NSPIoctl 1066 - sets cbSize to 44! */ 1067 lpRout->dwMajorVersion = 1; 1068 lpRout->dwMinorVersion = 1; 1069 lpRout->cbSize = sizeof(*lpRout) - sizeof(lpRout->NSPIoctl); 1070 lpRout->NSPCleanup = &mwsNSPCleanUp; 1071 lpRout->NSPLookupServiceBegin = &mwsNSPLookupServiceBegin; 1072 lpRout->NSPLookupServiceNext = &mwsNSPLookupServiceNext; 1073 lpRout->NSPLookupServiceEnd = &mwsNSPLookupServiceEnd; 1074 lpRout->NSPSetService = &mwsNSPSetService; 1075 lpRout->NSPInstallServiceClass = &mwsNSPInstallServiceClass; 1076 lpRout->NSPRemoveServiceClass = &mwsNSPRemoveServiceClass; 1077 lpRout->NSPGetServiceClassInfo = &mwsNSPGetServiceClassInfo; 1078 lpRout->NSPIoctl = NULL;// &mwsNSPIoCtl; 1079 1080 ret = NO_ERROR; 1081 1082 return ret; 1083 } 1084