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