1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS WinSock 2 API 4 * FILE: dll/win32/ws2_32_new/src/rnr.c 5 * PURPOSE: Registration and Resolution Support 6 * PROGRAMMER: Alex Ionescu (alex@relsoft.net) 7 */ 8 9 /* INCLUDES ******************************************************************/ 10 11 #include <ws2_32.h> 12 13 #define NDEBUG 14 #include <debug.h> 15 16 /* FUNCTIONS *****************************************************************/ 17 18 /* 19 * @implemented 20 */ 21 INT 22 WSAAPI 23 WSAAddressToStringA(IN LPSOCKADDR lpsaAddress, 24 IN DWORD dwAddressLength, 25 IN LPWSAPROTOCOL_INFOA lpProtocolInfo, 26 OUT LPSTR lpszAddressString, 27 IN OUT LPDWORD lpdwAddressStringLength) 28 { 29 PWSPROCESS Process; 30 PWSTHREAD Thread; 31 INT ErrorCode, Status; 32 DWORD CatalogEntryId; 33 PTCATALOG Catalog; 34 PTCATALOG_ENTRY CatalogEntry; 35 LPWSTR UnicodeString; 36 DWORD Length = *lpdwAddressStringLength; 37 38 DPRINT("WSAAddressToStringA: %p\n", lpsaAddress); 39 40 /* Enter prolog */ 41 if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS) 42 { 43 /* Leave now */ 44 SetLastError(ErrorCode); 45 return SOCKET_ERROR; 46 } 47 48 /* Allocate the unicode string */ 49 UnicodeString = HeapAlloc(WsSockHeap, 0, Length * 2); 50 if (!UnicodeString) 51 { 52 /* No memory; fail */ 53 SetLastError(WSAENOBUFS); 54 return SOCKET_ERROR; 55 } 56 57 /* Get the catalog */ 58 Catalog = WsProcGetTCatalog(Process); 59 60 /* Check if we got custom protocol info */ 61 if (lpProtocolInfo) 62 { 63 /* Get the entry ID */ 64 CatalogEntryId = lpProtocolInfo->dwCatalogEntryId; 65 66 /* Get the entry associated with it */ 67 ErrorCode = WsTcGetEntryFromCatalogEntryId(Catalog, 68 CatalogEntryId, 69 &CatalogEntry); 70 } 71 else 72 { 73 /* Get it from the address family */ 74 ErrorCode = WsTcGetEntryFromAf(Catalog, 75 lpsaAddress->sa_family, 76 &CatalogEntry); 77 } 78 79 /* Check for success */ 80 if (ErrorCode == ERROR_SUCCESS) 81 { 82 /* Call the provider */ 83 Status = CatalogEntry->Provider->Service.lpWSPAddressToString(lpsaAddress, 84 dwAddressLength, 85 &CatalogEntry-> 86 ProtocolInfo, 87 UnicodeString, 88 lpdwAddressStringLength, 89 &ErrorCode); 90 if (Status == ERROR_SUCCESS) 91 { 92 /* Convert the string */ 93 WideCharToMultiByte(CP_ACP, 94 0, 95 UnicodeString, 96 -1, 97 lpszAddressString, 98 Length, 99 NULL, 100 NULL); 101 } 102 103 /* Dereference the entry */ 104 WsTcEntryDereference(CatalogEntry); 105 106 /* Free the unicode string */ 107 HeapFree(WsSockHeap, 0, UnicodeString); 108 109 /* Check for success and return */ 110 if (Status == ERROR_SUCCESS) return ERROR_SUCCESS; 111 } 112 else 113 { 114 /* Free the unicode string */ 115 HeapFree(WsSockHeap, 0, UnicodeString); 116 } 117 118 /* Set the error and return */ 119 SetLastError(ErrorCode); 120 return SOCKET_ERROR; 121 } 122 123 /* 124 * @implemented 125 */ 126 INT 127 WSAAPI 128 WSAAddressToStringW(IN LPSOCKADDR lpsaAddress, 129 IN DWORD dwAddressLength, 130 IN LPWSAPROTOCOL_INFOW lpProtocolInfo, 131 OUT LPWSTR lpszAddressString, 132 IN OUT LPDWORD lpdwAddressStringLength) 133 { 134 PWSPROCESS Process; 135 PWSTHREAD Thread; 136 INT ErrorCode, Status; 137 DWORD CatalogEntryId; 138 PTCATALOG Catalog; 139 PTCATALOG_ENTRY CatalogEntry; 140 141 DPRINT("WSAAddressToStringW: %p\n", lpsaAddress); 142 143 /* Enter prolog */ 144 if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS) 145 { 146 /* Leave now */ 147 SetLastError(ErrorCode); 148 return SOCKET_ERROR; 149 } 150 151 /* Get the catalog */ 152 Catalog = WsProcGetTCatalog(Process); 153 154 /* Check if we got custom protocol info */ 155 if (lpProtocolInfo) 156 { 157 /* Get the entry ID */ 158 CatalogEntryId = lpProtocolInfo->dwCatalogEntryId; 159 160 /* Get the entry associated with it */ 161 ErrorCode = WsTcGetEntryFromCatalogEntryId(Catalog, 162 CatalogEntryId, 163 &CatalogEntry); 164 } 165 else 166 { 167 /* Get it from the address family */ 168 ErrorCode = WsTcGetEntryFromAf(Catalog, 169 lpsaAddress->sa_family, 170 &CatalogEntry); 171 } 172 173 /* Check for success */ 174 if (ErrorCode == ERROR_SUCCESS) 175 { 176 /* Call the provider */ 177 Status = CatalogEntry->Provider->Service.lpWSPAddressToString(lpsaAddress, 178 dwAddressLength, 179 &CatalogEntry-> 180 ProtocolInfo, 181 lpszAddressString, 182 lpdwAddressStringLength, 183 &ErrorCode); 184 185 /* Dereference the entry */ 186 WsTcEntryDereference(CatalogEntry); 187 188 /* Check for success and return */ 189 if (Status == ERROR_SUCCESS) return ERROR_SUCCESS; 190 } 191 192 /* Set the error and return */ 193 SetLastError(ErrorCode); 194 return SOCKET_ERROR; 195 } 196 197 /* 198 * @implemented 199 */ 200 INT 201 WSAAPI 202 WSALookupServiceEnd(IN HANDLE hLookup) 203 { 204 PWSPROCESS Process; 205 PWSTHREAD Thread; 206 INT ErrorCode; 207 PNSQUERY Query = hLookup; 208 209 DPRINT("WSALookupServiceEnd: %lx\n", hLookup); 210 211 /* Enter prolog */ 212 if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS) 213 { 214 /* Leave now */ 215 SetLastError(ErrorCode); 216 return SOCKET_ERROR; 217 } 218 219 /* Check for a valid handle, then validate and reference it */ 220 if (IsBadReadPtr(Query, sizeof(*Query)) || !WsNqValidateAndReference(Query)) 221 { 222 /* Fail */ 223 SetLastError(WSA_INVALID_HANDLE); 224 return SOCKET_ERROR; 225 } 226 227 /* Do the lookup */ 228 ErrorCode = WsNqLookupServiceEnd(Query); 229 230 /* Remove the validation reference */ 231 WsNqDereference(Query); 232 233 /* Remove the keep-alive */ 234 WsNqDereference(Query); 235 236 /* Return */ 237 return ERROR_SUCCESS; 238 } 239 240 /* 241 * @implemented 242 */ 243 INT 244 WSAAPI 245 WSALookupServiceBeginA(IN LPWSAQUERYSETA lpqsRestrictions, 246 IN DWORD dwControlFlags, 247 OUT LPHANDLE lphLookup) 248 { 249 INT ErrorCode; 250 LPWSAQUERYSETW UnicodeQuerySet = NULL; 251 SIZE_T UnicodeQuerySetSize = 0; 252 253 DPRINT("WSALookupServiceBeginA: %p\n", lpqsRestrictions); 254 255 /* Verify pointer */ 256 if (IsBadReadPtr(lpqsRestrictions, sizeof(*lpqsRestrictions)) || 257 IsBadReadPtr(lpqsRestrictions->lpServiceClassId, sizeof(*lpqsRestrictions->lpServiceClassId))) 258 { 259 /* Invalid */ 260 SetLastError(WSAEFAULT); 261 return SOCKET_ERROR; 262 } 263 264 /* Clear the reserved fields */ 265 lpqsRestrictions->dwOutputFlags = 0; 266 lpqsRestrictions->lpszComment = NULL; 267 lpqsRestrictions->dwNumberOfCsAddrs = 0; 268 269 /* Find out the side we'll need */ 270 ErrorCode = MapAnsiQuerySetToUnicode(lpqsRestrictions, 271 &UnicodeQuerySetSize, 272 UnicodeQuerySet); 273 274 /* We should've failed */ 275 if (ErrorCode == WSAEFAULT) 276 { 277 /* Allocate the buffer we'll need */ 278 UnicodeQuerySet = HeapAlloc(WsSockHeap, 0, UnicodeQuerySetSize); 279 if (UnicodeQuerySet) 280 { 281 /* Do the conversion for real */ 282 ErrorCode = MapAnsiQuerySetToUnicode(lpqsRestrictions, 283 &UnicodeQuerySetSize, 284 UnicodeQuerySet); 285 if (ErrorCode == ERROR_SUCCESS) 286 { 287 /* Now call the Unicode function */ 288 ErrorCode = WSALookupServiceBeginW(UnicodeQuerySet, 289 dwControlFlags, 290 lphLookup); 291 } 292 293 /* Free our buffer */ 294 HeapFree(WsSockHeap, 0, UnicodeQuerySet); 295 } 296 else 297 { 298 /* No memory to allocate */ 299 ErrorCode = WSAEFAULT; 300 } 301 } 302 303 /* Set the error in case of failure */ 304 if (ErrorCode != ERROR_SUCCESS) 305 SetLastError(ErrorCode); 306 307 /* Return to caller */ 308 return ErrorCode == ERROR_SUCCESS ? ErrorCode : SOCKET_ERROR; 309 } 310 311 /* 312 * @implemented 313 */ 314 INT 315 WINAPI 316 WSALookupServiceBeginW(IN LPWSAQUERYSETW lpqsRestrictions, 317 IN DWORD dwControlFlags, 318 OUT LPHANDLE lphLookup) 319 { 320 PWSPROCESS Process; 321 PWSTHREAD Thread; 322 INT ErrorCode; 323 PNSQUERY Query; 324 325 DPRINT("WSALookupServiceBeginW: %p\n", lpqsRestrictions); 326 327 /* Enter prolog */ 328 if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS) 329 { 330 /* Leave now */ 331 SetLastError(ErrorCode); 332 return SOCKET_ERROR; 333 } 334 335 /* Verify pointers */ 336 if (IsBadWritePtr(lphLookup, sizeof(*lphLookup)) || 337 IsBadReadPtr(lpqsRestrictions, sizeof(*lpqsRestrictions)) || 338 IsBadReadPtr(lpqsRestrictions->lpServiceClassId, sizeof(*lpqsRestrictions->lpServiceClassId))) 339 { 340 /* They are invalid; fail */ 341 SetLastError(WSAEFAULT); 342 return SOCKET_ERROR; 343 } 344 345 /* Create a new query object */ 346 if ((Query = WsNqAllocate())) 347 { 348 /* Initialize it */ 349 WsNqInitialize(Query); 350 351 /* Do the lookup */ 352 ErrorCode = WsNqLookupServiceBegin(Query, 353 lpqsRestrictions, 354 dwControlFlags, 355 WsProcGetNsCatalog(Process)); 356 357 /* Check for success */ 358 if (ErrorCode == ERROR_SUCCESS) 359 { 360 /* Return the handle */ 361 *lphLookup = Query; 362 } 363 else 364 { 365 /* Fail */ 366 *lphLookup = NULL; 367 WsNqDelete(Query); 368 } 369 } 370 else 371 { 372 /* No memory */ 373 ErrorCode = SOCKET_ERROR; 374 SetLastError(WSAENOBUFS); 375 } 376 377 /* Return */ 378 return ErrorCode; 379 } 380 381 /* 382 * @implemented 383 */ 384 INT 385 WINAPI 386 WSALookupServiceNextW(IN HANDLE hLookup, 387 IN DWORD dwControlFlags, 388 IN OUT LPDWORD lpdwBufferLength, 389 OUT LPWSAQUERYSETW lpqsResults) 390 { 391 PWSPROCESS Process; 392 PWSTHREAD Thread; 393 INT ErrorCode; 394 PNSQUERY Query = hLookup; 395 396 DPRINT("WSALookupServiceNextW: %lx\n", hLookup); 397 398 /* Enter prolog */ 399 if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS) 400 { 401 /* Leave now */ 402 SetLastError(ErrorCode); 403 return SOCKET_ERROR; 404 } 405 406 /* 407 * Verify pointers. Note that the size of the buffer 408 * pointed by lpqsResults is given by *lpdwBufferLength. 409 */ 410 if (IsBadReadPtr(lpdwBufferLength, sizeof(*lpdwBufferLength)) || 411 IsBadWritePtr(lpqsResults, *lpdwBufferLength)) 412 { 413 /* It is invalid; fail */ 414 SetLastError(WSAEFAULT); 415 return SOCKET_ERROR; 416 } 417 418 /* Check for a valid handle, then validate and reference it */ 419 if (IsBadReadPtr(Query, sizeof(*Query)) || !WsNqValidateAndReference(Query)) 420 { 421 /* Fail */ 422 SetLastError(WSA_INVALID_HANDLE); 423 return SOCKET_ERROR; 424 } 425 426 /* Do the lookup */ 427 ErrorCode = WsNqLookupServiceNext(Query, 428 dwControlFlags, 429 lpdwBufferLength, 430 lpqsResults); 431 432 /* Remove the validation reference */ 433 WsNqDereference(Query); 434 435 /* Return */ 436 return ErrorCode; 437 } 438 439 /* 440 * @implemented 441 */ 442 INT 443 WSAAPI 444 WSALookupServiceNextA(IN HANDLE hLookup, 445 IN DWORD dwControlFlags, 446 IN OUT LPDWORD lpdwBufferLength, 447 OUT LPWSAQUERYSETA lpqsResults) 448 { 449 LPWSAQUERYSETW UnicodeQuerySet; 450 DWORD UnicodeQuerySetSize; 451 INT ErrorCode; 452 453 DPRINT("WSALookupServiceNextA: %lx\n", hLookup); 454 455 /* 456 * Verify pointers. Note that the size of the buffer 457 * pointed by lpqsResults is given by *lpdwBufferLength. 458 */ 459 if (IsBadReadPtr(lpdwBufferLength, sizeof(*lpdwBufferLength)) || 460 IsBadWritePtr(lpqsResults, *lpdwBufferLength)) 461 { 462 /* It is invalid; fail */ 463 SetLastError(WSAEFAULT); 464 return SOCKET_ERROR; 465 } 466 467 UnicodeQuerySetSize = *lpdwBufferLength; 468 469 /* Check how much the user is giving */ 470 if (UnicodeQuerySetSize >= sizeof(WSAQUERYSETW)) 471 { 472 /* Allocate the buffer we'll use */ 473 UnicodeQuerySet = HeapAlloc(WsSockHeap, 0, UnicodeQuerySetSize); 474 if (!UnicodeQuerySet) 475 { 476 /* 477 * We failed, possibly because the specified size was too large? 478 * Retrieve the needed buffer size with the WSALookupServiceNextW 479 * call and retry again a second time. 480 */ 481 UnicodeQuerySetSize = 0; 482 } 483 } 484 else 485 { 486 /* 487 * The buffer is too small. Retrieve the needed buffer size with 488 * the WSALookupServiceNextW call and return it to the caller. 489 */ 490 UnicodeQuerySet = NULL; 491 UnicodeQuerySetSize = 0; 492 } 493 494 /* Call the Unicode Function */ 495 ErrorCode = WSALookupServiceNextW(hLookup, 496 dwControlFlags, 497 &UnicodeQuerySetSize, 498 UnicodeQuerySet); 499 500 /* 501 * Check whether we actually just retrieved the needed buffer size 502 * because our previous local allocation did fail. If so, allocate 503 * a new buffer and retry again. 504 */ 505 if ( (!UnicodeQuerySet) && (*lpdwBufferLength >= sizeof(WSAQUERYSETW)) && 506 (ErrorCode == SOCKET_ERROR) && (GetLastError() == WSAEFAULT) ) 507 { 508 /* Allocate the buffer we'll use */ 509 UnicodeQuerySet = HeapAlloc(WsSockHeap, 0, UnicodeQuerySetSize); 510 if (UnicodeQuerySet) 511 { 512 /* Call the Unicode Function */ 513 ErrorCode = WSALookupServiceNextW(hLookup, 514 dwControlFlags, 515 &UnicodeQuerySetSize, 516 UnicodeQuerySet); 517 } 518 /* 519 * Otherwise the allocation failed and we 520 * fall back into the error checks below. 521 */ 522 } 523 524 if (ErrorCode == ERROR_SUCCESS) 525 { 526 SIZE_T SetSize = *lpdwBufferLength; 527 528 /* Now convert back to ANSI */ 529 ErrorCode = MapUnicodeQuerySetToAnsi(UnicodeQuerySet, 530 &SetSize, 531 lpqsResults); 532 if (ErrorCode != ERROR_SUCCESS) 533 { 534 SetLastError(ErrorCode); 535 } 536 else if (SetSize > MAXDWORD) 537 { 538 ErrorCode = ERROR_ARITHMETIC_OVERFLOW; 539 SetLastError(ErrorCode); 540 } 541 else 542 { 543 *lpdwBufferLength = SetSize; 544 } 545 } 546 else 547 { 548 /* Check if we ran out of space */ 549 if (GetLastError() == WSAEFAULT) 550 { 551 /* Return how much space we'll need, including padding */ 552 *lpdwBufferLength = UnicodeQuerySetSize + 553 ((sizeof(ULONG) * 6) - (6 * 1)); 554 } 555 } 556 557 /* If we had a local buffer, free it */ 558 if (UnicodeQuerySet) 559 HeapFree(WsSockHeap, 0, UnicodeQuerySet); 560 561 /* Return to caller */ 562 return (ErrorCode == ERROR_SUCCESS) ? ErrorCode : SOCKET_ERROR; 563 } 564 565 /* 566 * @unimplemented 567 */ 568 INT 569 WSPAPI 570 WSANSPIoctl(HANDLE hLookup, 571 DWORD dwControlCode, 572 LPVOID lpvInBuffer, 573 DWORD cbInBuffer, 574 LPVOID lpvOutBuffer, 575 DWORD cbOutBuffer, 576 LPDWORD lpcbBytesReturned, 577 LPWSACOMPLETION lpCompletion) 578 { 579 DPRINT("WSANSPIoctl: %lx\n", hLookup); 580 return 0; 581 } 582 583 /* 584 * @unimplemented 585 */ 586 INT 587 WSAAPI 588 WSARemoveServiceClass(IN LPGUID lpServiceClassId) 589 { 590 DPRINT("WSARemoveServiceClass: %lx\n", lpServiceClassId); 591 SetLastError(WSAEINVAL); 592 return SOCKET_ERROR; 593 } 594 595 /* 596 * @unimplemented 597 */ 598 INT 599 WSAAPI 600 WSASetServiceA(IN LPWSAQUERYSETA lpqsRegInfo, 601 IN WSAESETSERVICEOP essOperation, 602 IN DWORD dwControlFlags) 603 { 604 DPRINT("WSASetServiceA: %lx\n", lpqsRegInfo); 605 SetLastError(WSAEINVAL); 606 return SOCKET_ERROR; 607 } 608 609 /* 610 * @unimplemented 611 */ 612 INT 613 WSAAPI 614 WSASetServiceW(IN LPWSAQUERYSETW lpqsRegInfo, 615 IN WSAESETSERVICEOP essOperation, 616 IN DWORD dwControlFlags) 617 { 618 DPRINT("WSASetServiceW: %lx\n", lpqsRegInfo); 619 SetLastError(WSAEINVAL); 620 return SOCKET_ERROR; 621 } 622 623 /* 624 * @unimplemented 625 */ 626 INT 627 WSAAPI 628 WSAGetServiceClassInfoA(IN LPGUID lpProviderId, 629 IN LPGUID lpServiceClassId, 630 IN OUT LPDWORD lpdwBufferLength, 631 OUT LPWSASERVICECLASSINFOA lpServiceClassInfo) 632 { 633 DPRINT("WSAGetServiceClassInfoA: %lx\n", lpProviderId); 634 SetLastError(WSAEINVAL); 635 return SOCKET_ERROR; 636 } 637 638 /* 639 * @unimplemented 640 */ 641 INT 642 WSAAPI 643 WSAGetServiceClassInfoW(IN LPGUID lpProviderId, 644 IN LPGUID lpServiceClassId, 645 IN OUT LPDWORD lpdwBufferLength, 646 OUT LPWSASERVICECLASSINFOW lpServiceClassInfo) 647 { 648 DPRINT("WSAGetServiceClassInfoW: %lx\n", lpProviderId); 649 SetLastError(WSAEINVAL); 650 return SOCKET_ERROR; 651 } 652 653 /* 654 * @unimplemented 655 */ 656 INT 657 WSAAPI 658 WSAGetServiceClassNameByClassIdA(IN LPGUID lpServiceClassId, 659 OUT LPSTR lpszServiceClassName, 660 IN OUT LPDWORD lpdwBufferLength) 661 { 662 DPRINT("WSAGetServiceClassNameByClassIdA: %lx\n", lpServiceClassId); 663 SetLastError(WSAEINVAL); 664 return SOCKET_ERROR; 665 } 666 667 /* 668 * @unimplemented 669 */ 670 INT 671 WSAAPI 672 WSAGetServiceClassNameByClassIdW(IN LPGUID lpServiceClassId, 673 OUT LPWSTR lpszServiceClassName, 674 IN OUT LPDWORD lpdwBufferLength) 675 { 676 DPRINT("WSAGetServiceClassNameByClassIdW: %lx\n", lpServiceClassId); 677 SetLastError(WSAEINVAL); 678 return SOCKET_ERROR; 679 } 680 681 /* 682 * @unimplemented 683 */ 684 INT 685 WSAAPI 686 WSAInstallServiceClassA(IN LPWSASERVICECLASSINFOA lpServiceClassInfo) 687 { 688 DPRINT("WSAInstallServiceClassA: %lx\n", lpServiceClassInfo); 689 SetLastError(WSAEINVAL); 690 return SOCKET_ERROR; 691 } 692 693 /* 694 * @unimplemented 695 */ 696 INT 697 WSAAPI 698 WSAInstallServiceClassW(IN LPWSASERVICECLASSINFOW lpServiceClassInfo) 699 { 700 DPRINT("WSAInstallServiceClassW: %lx\n", lpServiceClassInfo); 701 SetLastError(WSAEINVAL); 702 return SOCKET_ERROR; 703 } 704 705 VOID 706 WSAAPI 707 NSProviderInfoFromContext(IN PNSCATALOG_ENTRY Entry, 708 IN PNSPROVIDER_ENUM_CONTEXT Context) 709 { 710 INT size = Context->Unicode ? sizeof(WSANAMESPACE_INFOW) : sizeof(WSANAMESPACE_INFOA); 711 /* Calculate ProviderName string size */ 712 INT size1 = Entry->ProviderName ? wcslen(Entry->ProviderName) + 1 : 0; 713 INT size2 = Context->Unicode ? size1 * sizeof(WCHAR) : size1 * sizeof(CHAR); 714 WSANAMESPACE_INFOW infoW; 715 /* Fill NS Provider data */ 716 infoW.dwNameSpace = Entry->NamespaceId; 717 infoW.dwVersion = Entry->Version; 718 infoW.fActive = Entry->Enabled; 719 RtlMoveMemory(&infoW.NSProviderId, 720 &Entry->ProviderId, 721 sizeof(infoW.NSProviderId)); 722 if (size2) 723 { 724 /* Calculate ProviderName string pointer */ 725 infoW.lpszIdentifier = (LPWSTR)((ULONG_PTR)Context->ProtocolBuffer + 726 Context->BufferUsed + size); 727 } 728 else 729 { 730 infoW.lpszIdentifier = NULL; 731 } 732 733 /* Check if we'll have space */ 734 if ((Context->BufferUsed + size + size2) <= 735 (Context->BufferLength)) 736 { 737 /* Copy the data */ 738 RtlMoveMemory((PVOID)((ULONG_PTR)Context->ProtocolBuffer + 739 Context->BufferUsed), 740 &infoW, 741 size); 742 if (size2) 743 { 744 /* Entry->ProviderName is LPWSTR */ 745 if (Context->Unicode) 746 { 747 RtlMoveMemory((PVOID)((ULONG_PTR)Context->ProtocolBuffer + 748 Context->BufferUsed + size), 749 Entry->ProviderName, 750 size2); 751 } 752 else 753 { 754 /* Call the conversion function */ 755 WideCharToMultiByte(CP_ACP, 756 0, 757 Entry->ProviderName, 758 -1, 759 (LPSTR)((ULONG_PTR)Context->ProtocolBuffer + 760 Context->BufferUsed + size), 761 size2, 762 NULL, 763 NULL); 764 765 } 766 } 767 768 /* Increase the count */ 769 Context->Count++; 770 } 771 } 772 773 BOOL 774 WSAAPI 775 NSProvidersEnumerationProc(PVOID EnumContext, 776 PNSCATALOG_ENTRY Entry) 777 { 778 PNSPROVIDER_ENUM_CONTEXT Context = (PNSPROVIDER_ENUM_CONTEXT)EnumContext; 779 780 /* Calculate ProviderName string size */ 781 INT size1 = Entry->ProviderName ? wcslen(Entry->ProviderName) + 1 : 0; 782 INT size2 = Context->Unicode ? size1 * sizeof(WCHAR) : size1 * sizeof(CHAR); 783 784 /* Copy the information */ 785 NSProviderInfoFromContext(Entry, Context); 786 Context->BufferUsed += Context->Unicode ? (sizeof(WSANAMESPACE_INFOW)+size2) : (sizeof(WSANAMESPACE_INFOA)+size2); 787 788 /* Continue enumeration */ 789 return TRUE; 790 } 791 792 INT 793 WSAAPI 794 WSAEnumNameSpaceProvidersInternal(IN OUT LPDWORD lpdwBufferLength, 795 OUT LPWSANAMESPACE_INFOA lpnspBuffer, BOOLEAN Unicode) 796 { 797 INT Status; 798 PWSPROCESS WsProcess; 799 PNSCATALOG Catalog; 800 NSPROVIDER_ENUM_CONTEXT Context; 801 802 DPRINT("WSAEnumNameSpaceProvidersInternal: %lx\n", lpnspBuffer); 803 804 if (!lpdwBufferLength) 805 { 806 WSASetLastError(WSAEFAULT); 807 return SOCKET_ERROR; 808 } 809 WsProcess = WsGetProcess(); 810 /* Create a catalog object from the current one */ 811 Catalog = WsProcGetNsCatalog(WsProcess); 812 if (!Catalog) 813 { 814 /* Fail if we couldn't */ 815 WSASetLastError(WSA_NOT_ENOUGH_MEMORY); 816 return SOCKET_ERROR; 817 } 818 819 Context.ProtocolBuffer = lpnspBuffer; 820 Context.BufferLength = lpnspBuffer ? *lpdwBufferLength : 0; 821 Context.BufferUsed = 0; 822 Context.Count = 0; 823 Context.Unicode = Unicode; 824 Context.ErrorCode = ERROR_SUCCESS; 825 826 WsNcEnumerateCatalogItems(Catalog, NSProvidersEnumerationProc, &Context); 827 828 /* Get status */ 829 Status = Context.Count; 830 831 /* Check the error code */ 832 if (Context.ErrorCode == ERROR_SUCCESS) 833 { 834 /* Check if enough space was available */ 835 if (Context.BufferLength < Context.BufferUsed) 836 { 837 /* Fail and tell them how much we need */ 838 *lpdwBufferLength = Context.BufferUsed; 839 WSASetLastError(WSAEFAULT); 840 Status = SOCKET_ERROR; 841 } 842 } 843 else 844 { 845 /* Failure, normalize error */ 846 Status = SOCKET_ERROR; 847 WSASetLastError(Context.ErrorCode); 848 } 849 850 /* Return */ 851 return Status; 852 } 853 854 /* 855 * @implemented 856 */ 857 INT 858 WSAAPI 859 WSAEnumNameSpaceProvidersA(IN OUT LPDWORD lpdwBufferLength, 860 OUT LPWSANAMESPACE_INFOA lpnspBuffer) 861 { 862 DPRINT("WSAEnumNameSpaceProvidersA: %lx\n", lpnspBuffer); 863 return WSAEnumNameSpaceProvidersInternal(lpdwBufferLength, (LPWSANAMESPACE_INFOA)lpnspBuffer, FALSE); 864 } 865 866 /* 867 * @implemented 868 */ 869 INT 870 WSAAPI 871 WSAEnumNameSpaceProvidersW(IN OUT LPDWORD lpdwBufferLength, 872 OUT LPWSANAMESPACE_INFOW lpnspBuffer) 873 { 874 DPRINT("WSAEnumNameSpaceProvidersW: %lx\n", lpnspBuffer); 875 return WSAEnumNameSpaceProvidersInternal(lpdwBufferLength, (LPWSANAMESPACE_INFOA)lpnspBuffer, TRUE); 876 } 877 878 /* 879 * @implemented 880 */ 881 INT 882 WSAAPI 883 WSAStringToAddressA(IN LPSTR AddressString, 884 IN INT AddressFamily, 885 IN LPWSAPROTOCOL_INFOA lpProtocolInfo, 886 OUT LPSOCKADDR lpAddress, 887 IN OUT LPINT lpAddressLength) 888 { 889 PWSPROCESS Process; 890 PWSTHREAD Thread; 891 INT ErrorCode, Status; 892 DWORD CatalogEntryId; 893 PTCATALOG Catalog; 894 PTCATALOG_ENTRY CatalogEntry; 895 LPWSTR UnicodeString; 896 DWORD Length = (DWORD)strlen(AddressString) + 1; 897 898 DPRINT("WSAStringToAddressA: %s\n", AddressString); 899 900 /* Enter prolog */ 901 if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS) 902 { 903 /* Leave now */ 904 SetLastError(ErrorCode); 905 return SOCKET_ERROR; 906 } 907 908 /* Allocate the unicode string */ 909 UnicodeString = HeapAlloc(WsSockHeap, 0, Length * 2); 910 if (!UnicodeString) 911 { 912 /* No memory; fail */ 913 SetLastError(WSAENOBUFS); 914 return SOCKET_ERROR; 915 } 916 917 /* Convert the string */ 918 MultiByteToWideChar(CP_ACP, 0, AddressString, -1, UnicodeString, Length); 919 920 /* Get the catalog */ 921 Catalog = WsProcGetTCatalog(Process); 922 923 /* Check if we got custom protocol info */ 924 if (lpProtocolInfo) 925 { 926 /* Get the entry ID */ 927 CatalogEntryId = lpProtocolInfo->dwCatalogEntryId; 928 929 /* Get the entry associated with it */ 930 ErrorCode = WsTcGetEntryFromCatalogEntryId(Catalog, 931 CatalogEntryId, 932 &CatalogEntry); 933 } 934 else 935 { 936 /* Get it from the address family */ 937 ErrorCode = WsTcGetEntryFromAf(Catalog, AddressFamily, &CatalogEntry); 938 } 939 940 /* Check for success */ 941 if (ErrorCode == ERROR_SUCCESS) 942 { 943 /* Call the provider */ 944 Status = CatalogEntry->Provider->Service.lpWSPStringToAddress(UnicodeString, 945 AddressFamily, 946 &CatalogEntry-> 947 ProtocolInfo, 948 lpAddress, 949 lpAddressLength, 950 &ErrorCode); 951 952 /* Dereference the entry */ 953 WsTcEntryDereference(CatalogEntry); 954 955 /* Free the unicode string */ 956 HeapFree(WsSockHeap, 0, UnicodeString); 957 958 /* Check for success and return */ 959 if (Status == ERROR_SUCCESS) return ERROR_SUCCESS; 960 } 961 else 962 { 963 /* Free the unicode string */ 964 HeapFree(WsSockHeap, 0, UnicodeString); 965 } 966 967 /* Set the error and return */ 968 SetLastError(ErrorCode); 969 return SOCKET_ERROR; 970 } 971 972 /* 973 * @implemented 974 */ 975 INT 976 WSAAPI 977 WSAStringToAddressW(IN LPWSTR AddressString, 978 IN INT AddressFamily, 979 IN LPWSAPROTOCOL_INFOW lpProtocolInfo, 980 OUT LPSOCKADDR lpAddress, 981 IN OUT LPINT lpAddressLength) 982 { 983 PWSPROCESS Process; 984 PWSTHREAD Thread; 985 INT ErrorCode, Status; 986 DWORD CatalogEntryId; 987 PTCATALOG Catalog; 988 PTCATALOG_ENTRY CatalogEntry; 989 990 DPRINT("WSAStringToAddressW: %S\n", AddressString); 991 992 /* Enter prolog */ 993 if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS) 994 { 995 /* Leave now */ 996 SetLastError(ErrorCode); 997 return SOCKET_ERROR; 998 } 999 1000 /* Get the catalog */ 1001 Catalog = WsProcGetTCatalog(Process); 1002 1003 /* Check if we got custom protocol info */ 1004 if (lpProtocolInfo) 1005 { 1006 /* Get the entry ID */ 1007 CatalogEntryId = lpProtocolInfo->dwCatalogEntryId; 1008 1009 /* Get the entry associated with it */ 1010 ErrorCode = WsTcGetEntryFromCatalogEntryId(Catalog, 1011 CatalogEntryId, 1012 &CatalogEntry); 1013 } 1014 else 1015 { 1016 /* Get it from the address family */ 1017 ErrorCode = WsTcGetEntryFromAf(Catalog, AddressFamily, &CatalogEntry); 1018 } 1019 1020 /* Check for success */ 1021 if (ErrorCode == ERROR_SUCCESS) 1022 { 1023 /* Call the provider */ 1024 Status = CatalogEntry->Provider->Service.lpWSPStringToAddress(AddressString, 1025 AddressFamily, 1026 &CatalogEntry-> 1027 ProtocolInfo, 1028 lpAddress, 1029 lpAddressLength, 1030 &ErrorCode); 1031 1032 /* Dereference the entry */ 1033 WsTcEntryDereference(CatalogEntry); 1034 1035 /* Check for success and return */ 1036 if (Status == ERROR_SUCCESS) return ERROR_SUCCESS; 1037 } 1038 1039 /* Set the error and return */ 1040 SetLastError(ErrorCode); 1041 return SOCKET_ERROR; 1042 } 1043