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 DWORD 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 /* Now convert back to ANSI */ 527 ErrorCode = MapUnicodeQuerySetToAnsi(UnicodeQuerySet, 528 lpdwBufferLength, 529 lpqsResults); 530 if (ErrorCode != ERROR_SUCCESS) 531 SetLastError(ErrorCode); 532 } 533 else 534 { 535 /* Check if we ran out of space */ 536 if (GetLastError() == WSAEFAULT) 537 { 538 /* Return how much space we'll need, including padding */ 539 *lpdwBufferLength = UnicodeQuerySetSize + 540 ((sizeof(ULONG) * 6) - (6 * 1)); 541 } 542 } 543 544 /* If we had a local buffer, free it */ 545 if (UnicodeQuerySet) 546 HeapFree(WsSockHeap, 0, UnicodeQuerySet); 547 548 /* Return to caller */ 549 return (ErrorCode == ERROR_SUCCESS) ? ErrorCode : SOCKET_ERROR; 550 } 551 552 /* 553 * @unimplemented 554 */ 555 INT 556 WSPAPI 557 WSANSPIoctl(HANDLE hLookup, 558 DWORD dwControlCode, 559 LPVOID lpvInBuffer, 560 DWORD cbInBuffer, 561 LPVOID lpvOutBuffer, 562 DWORD cbOutBuffer, 563 LPDWORD lpcbBytesReturned, 564 LPWSACOMPLETION lpCompletion) 565 { 566 DPRINT("WSANSPIoctl: %lx\n", hLookup); 567 return 0; 568 } 569 570 /* 571 * @unimplemented 572 */ 573 INT 574 WSAAPI 575 WSARemoveServiceClass(IN LPGUID lpServiceClassId) 576 { 577 DPRINT("WSARemoveServiceClass: %lx\n", lpServiceClassId); 578 SetLastError(WSAEINVAL); 579 return SOCKET_ERROR; 580 } 581 582 /* 583 * @unimplemented 584 */ 585 INT 586 WSAAPI 587 WSASetServiceA(IN LPWSAQUERYSETA lpqsRegInfo, 588 IN WSAESETSERVICEOP essOperation, 589 IN DWORD dwControlFlags) 590 { 591 DPRINT("WSASetServiceA: %lx\n", lpqsRegInfo); 592 SetLastError(WSAEINVAL); 593 return SOCKET_ERROR; 594 } 595 596 /* 597 * @unimplemented 598 */ 599 INT 600 WSAAPI 601 WSASetServiceW(IN LPWSAQUERYSETW lpqsRegInfo, 602 IN WSAESETSERVICEOP essOperation, 603 IN DWORD dwControlFlags) 604 { 605 DPRINT("WSASetServiceW: %lx\n", lpqsRegInfo); 606 SetLastError(WSAEINVAL); 607 return SOCKET_ERROR; 608 } 609 610 /* 611 * @unimplemented 612 */ 613 INT 614 WSAAPI 615 WSAGetServiceClassInfoA(IN LPGUID lpProviderId, 616 IN LPGUID lpServiceClassId, 617 IN OUT LPDWORD lpdwBufferLength, 618 OUT LPWSASERVICECLASSINFOA lpServiceClassInfo) 619 { 620 DPRINT("WSAGetServiceClassInfoA: %lx\n", lpProviderId); 621 SetLastError(WSAEINVAL); 622 return SOCKET_ERROR; 623 } 624 625 /* 626 * @unimplemented 627 */ 628 INT 629 WSAAPI 630 WSAGetServiceClassInfoW(IN LPGUID lpProviderId, 631 IN LPGUID lpServiceClassId, 632 IN OUT LPDWORD lpdwBufferLength, 633 OUT LPWSASERVICECLASSINFOW lpServiceClassInfo) 634 { 635 DPRINT("WSAGetServiceClassInfoW: %lx\n", lpProviderId); 636 SetLastError(WSAEINVAL); 637 return SOCKET_ERROR; 638 } 639 640 /* 641 * @unimplemented 642 */ 643 INT 644 WSAAPI 645 WSAGetServiceClassNameByClassIdA(IN LPGUID lpServiceClassId, 646 OUT LPSTR lpszServiceClassName, 647 IN OUT LPDWORD lpdwBufferLength) 648 { 649 DPRINT("WSAGetServiceClassNameByClassIdA: %lx\n", lpServiceClassId); 650 SetLastError(WSAEINVAL); 651 return SOCKET_ERROR; 652 } 653 654 /* 655 * @unimplemented 656 */ 657 INT 658 WSAAPI 659 WSAGetServiceClassNameByClassIdW(IN LPGUID lpServiceClassId, 660 OUT LPWSTR lpszServiceClassName, 661 IN OUT LPDWORD lpdwBufferLength) 662 { 663 DPRINT("WSAGetServiceClassNameByClassIdW: %lx\n", lpServiceClassId); 664 SetLastError(WSAEINVAL); 665 return SOCKET_ERROR; 666 } 667 668 /* 669 * @unimplemented 670 */ 671 INT 672 WSAAPI 673 WSAInstallServiceClassA(IN LPWSASERVICECLASSINFOA lpServiceClassInfo) 674 { 675 DPRINT("WSAInstallServiceClassA: %lx\n", lpServiceClassInfo); 676 SetLastError(WSAEINVAL); 677 return SOCKET_ERROR; 678 } 679 680 /* 681 * @unimplemented 682 */ 683 INT 684 WSAAPI 685 WSAInstallServiceClassW(IN LPWSASERVICECLASSINFOW lpServiceClassInfo) 686 { 687 DPRINT("WSAInstallServiceClassW: %lx\n", lpServiceClassInfo); 688 SetLastError(WSAEINVAL); 689 return SOCKET_ERROR; 690 } 691 692 VOID 693 WSAAPI 694 NSProviderInfoFromContext(IN PNSCATALOG_ENTRY Entry, 695 IN PNSPROVIDER_ENUM_CONTEXT Context) 696 { 697 INT size = Context->Unicode ? sizeof(WSANAMESPACE_INFOW) : sizeof(WSANAMESPACE_INFOA); 698 /* Calculate ProviderName string size */ 699 INT size1 = Entry->ProviderName ? wcslen(Entry->ProviderName) + 1 : 0; 700 INT size2 = Context->Unicode ? size1 * sizeof(WCHAR) : size1 * sizeof(CHAR); 701 WSANAMESPACE_INFOW infoW; 702 /* Fill NS Provider data */ 703 infoW.dwNameSpace = Entry->NamespaceId; 704 infoW.dwVersion = Entry->Version; 705 infoW.fActive = Entry->Enabled; 706 RtlMoveMemory(&infoW.NSProviderId, 707 &Entry->ProviderId, 708 sizeof(infoW.NSProviderId)); 709 if (size2) 710 { 711 /* Calculate ProviderName string pointer */ 712 infoW.lpszIdentifier = (LPWSTR)((ULONG_PTR)Context->ProtocolBuffer + 713 Context->BufferUsed + size); 714 } 715 else 716 { 717 infoW.lpszIdentifier = NULL; 718 } 719 720 /* Check if we'll have space */ 721 if ((Context->BufferUsed + size + size2) <= 722 (Context->BufferLength)) 723 { 724 /* Copy the data */ 725 RtlMoveMemory((PVOID)((ULONG_PTR)Context->ProtocolBuffer + 726 Context->BufferUsed), 727 &infoW, 728 size); 729 if (size2) 730 { 731 /* Entry->ProviderName is LPWSTR */ 732 if (Context->Unicode) 733 { 734 RtlMoveMemory((PVOID)((ULONG_PTR)Context->ProtocolBuffer + 735 Context->BufferUsed + size), 736 Entry->ProviderName, 737 size2); 738 } 739 else 740 { 741 /* Call the conversion function */ 742 WideCharToMultiByte(CP_ACP, 743 0, 744 Entry->ProviderName, 745 -1, 746 (LPSTR)((ULONG_PTR)Context->ProtocolBuffer + 747 Context->BufferUsed + size), 748 size2, 749 NULL, 750 NULL); 751 752 } 753 } 754 755 /* Increase the count */ 756 Context->Count++; 757 } 758 } 759 760 BOOL 761 WSAAPI 762 NSProvidersEnumerationProc(PVOID EnumContext, 763 PNSCATALOG_ENTRY Entry) 764 { 765 PNSPROVIDER_ENUM_CONTEXT Context = (PNSPROVIDER_ENUM_CONTEXT)EnumContext; 766 767 /* Calculate ProviderName string size */ 768 INT size1 = Entry->ProviderName ? wcslen(Entry->ProviderName) + 1 : 0; 769 INT size2 = Context->Unicode ? size1 * sizeof(WCHAR) : size1 * sizeof(CHAR); 770 771 /* Copy the information */ 772 NSProviderInfoFromContext(Entry, Context); 773 Context->BufferUsed += Context->Unicode ? (sizeof(WSANAMESPACE_INFOW)+size2) : (sizeof(WSANAMESPACE_INFOA)+size2); 774 775 /* Continue enumeration */ 776 return TRUE; 777 } 778 779 INT 780 WSAAPI 781 WSAEnumNameSpaceProvidersInternal(IN OUT LPDWORD lpdwBufferLength, 782 OUT LPWSANAMESPACE_INFOA lpnspBuffer, BOOLEAN Unicode) 783 { 784 INT Status; 785 PWSPROCESS WsProcess; 786 PNSCATALOG Catalog; 787 NSPROVIDER_ENUM_CONTEXT Context; 788 789 DPRINT("WSAEnumNameSpaceProvidersInternal: %lx\n", lpnspBuffer); 790 791 if (!lpdwBufferLength) 792 { 793 WSASetLastError(WSAEFAULT); 794 return SOCKET_ERROR; 795 } 796 WsProcess = WsGetProcess(); 797 /* Create a catalog object from the current one */ 798 Catalog = WsProcGetNsCatalog(WsProcess); 799 if (!Catalog) 800 { 801 /* Fail if we couldn't */ 802 WSASetLastError(WSA_NOT_ENOUGH_MEMORY); 803 return SOCKET_ERROR; 804 } 805 806 Context.ProtocolBuffer = lpnspBuffer; 807 Context.BufferLength = lpnspBuffer ? *lpdwBufferLength : 0; 808 Context.BufferUsed = 0; 809 Context.Count = 0; 810 Context.Unicode = Unicode; 811 Context.ErrorCode = ERROR_SUCCESS; 812 813 WsNcEnumerateCatalogItems(Catalog, NSProvidersEnumerationProc, &Context); 814 815 /* Get status */ 816 Status = Context.Count; 817 818 /* Check the error code */ 819 if (Context.ErrorCode == ERROR_SUCCESS) 820 { 821 /* Check if enough space was available */ 822 if (Context.BufferLength < Context.BufferUsed) 823 { 824 /* Fail and tell them how much we need */ 825 *lpdwBufferLength = Context.BufferUsed; 826 WSASetLastError(WSAEFAULT); 827 Status = SOCKET_ERROR; 828 } 829 } 830 else 831 { 832 /* Failure, normalize error */ 833 Status = SOCKET_ERROR; 834 WSASetLastError(Context.ErrorCode); 835 } 836 837 /* Return */ 838 return Status; 839 } 840 841 /* 842 * @implemented 843 */ 844 INT 845 WSAAPI 846 WSAEnumNameSpaceProvidersA(IN OUT LPDWORD lpdwBufferLength, 847 OUT LPWSANAMESPACE_INFOA lpnspBuffer) 848 { 849 DPRINT("WSAEnumNameSpaceProvidersA: %lx\n", lpnspBuffer); 850 return WSAEnumNameSpaceProvidersInternal(lpdwBufferLength, (LPWSANAMESPACE_INFOA)lpnspBuffer, FALSE); 851 } 852 853 /* 854 * @implemented 855 */ 856 INT 857 WSAAPI 858 WSAEnumNameSpaceProvidersW(IN OUT LPDWORD lpdwBufferLength, 859 OUT LPWSANAMESPACE_INFOW lpnspBuffer) 860 { 861 DPRINT("WSAEnumNameSpaceProvidersW: %lx\n", lpnspBuffer); 862 return WSAEnumNameSpaceProvidersInternal(lpdwBufferLength, (LPWSANAMESPACE_INFOA)lpnspBuffer, TRUE); 863 } 864 865 /* 866 * @implemented 867 */ 868 INT 869 WSAAPI 870 WSAStringToAddressA(IN LPSTR AddressString, 871 IN INT AddressFamily, 872 IN LPWSAPROTOCOL_INFOA lpProtocolInfo, 873 OUT LPSOCKADDR lpAddress, 874 IN OUT LPINT lpAddressLength) 875 { 876 PWSPROCESS Process; 877 PWSTHREAD Thread; 878 INT ErrorCode, Status; 879 DWORD CatalogEntryId; 880 PTCATALOG Catalog; 881 PTCATALOG_ENTRY CatalogEntry; 882 LPWSTR UnicodeString; 883 DWORD Length = (DWORD)strlen(AddressString) + 1; 884 885 DPRINT("WSAStringToAddressA: %s\n", AddressString); 886 887 /* Enter prolog */ 888 if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS) 889 { 890 /* Leave now */ 891 SetLastError(ErrorCode); 892 return SOCKET_ERROR; 893 } 894 895 /* Allocate the unicode string */ 896 UnicodeString = HeapAlloc(WsSockHeap, 0, Length * 2); 897 if (!UnicodeString) 898 { 899 /* No memory; fail */ 900 SetLastError(WSAENOBUFS); 901 return SOCKET_ERROR; 902 } 903 904 /* Convert the string */ 905 MultiByteToWideChar(CP_ACP, 0, AddressString, -1, UnicodeString, Length); 906 907 /* Get the catalog */ 908 Catalog = WsProcGetTCatalog(Process); 909 910 /* Check if we got custom protocol info */ 911 if (lpProtocolInfo) 912 { 913 /* Get the entry ID */ 914 CatalogEntryId = lpProtocolInfo->dwCatalogEntryId; 915 916 /* Get the entry associated with it */ 917 ErrorCode = WsTcGetEntryFromCatalogEntryId(Catalog, 918 CatalogEntryId, 919 &CatalogEntry); 920 } 921 else 922 { 923 /* Get it from the address family */ 924 ErrorCode = WsTcGetEntryFromAf(Catalog, AddressFamily, &CatalogEntry); 925 } 926 927 /* Check for success */ 928 if (ErrorCode == ERROR_SUCCESS) 929 { 930 /* Call the provider */ 931 Status = CatalogEntry->Provider->Service.lpWSPStringToAddress(UnicodeString, 932 AddressFamily, 933 &CatalogEntry-> 934 ProtocolInfo, 935 lpAddress, 936 lpAddressLength, 937 &ErrorCode); 938 939 /* Dereference the entry */ 940 WsTcEntryDereference(CatalogEntry); 941 942 /* Free the unicode string */ 943 HeapFree(WsSockHeap, 0, UnicodeString); 944 945 /* Check for success and return */ 946 if (Status == ERROR_SUCCESS) return ERROR_SUCCESS; 947 } 948 else 949 { 950 /* Free the unicode string */ 951 HeapFree(WsSockHeap, 0, UnicodeString); 952 } 953 954 /* Set the error and return */ 955 SetLastError(ErrorCode); 956 return SOCKET_ERROR; 957 } 958 959 /* 960 * @implemented 961 */ 962 INT 963 WSAAPI 964 WSAStringToAddressW(IN LPWSTR AddressString, 965 IN INT AddressFamily, 966 IN LPWSAPROTOCOL_INFOW lpProtocolInfo, 967 OUT LPSOCKADDR lpAddress, 968 IN OUT LPINT lpAddressLength) 969 { 970 PWSPROCESS Process; 971 PWSTHREAD Thread; 972 INT ErrorCode, Status; 973 DWORD CatalogEntryId; 974 PTCATALOG Catalog; 975 PTCATALOG_ENTRY CatalogEntry; 976 977 DPRINT("WSAStringToAddressW: %S\n", AddressString); 978 979 /* Enter prolog */ 980 if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS) 981 { 982 /* Leave now */ 983 SetLastError(ErrorCode); 984 return SOCKET_ERROR; 985 } 986 987 /* Get the catalog */ 988 Catalog = WsProcGetTCatalog(Process); 989 990 /* Check if we got custom protocol info */ 991 if (lpProtocolInfo) 992 { 993 /* Get the entry ID */ 994 CatalogEntryId = lpProtocolInfo->dwCatalogEntryId; 995 996 /* Get the entry associated with it */ 997 ErrorCode = WsTcGetEntryFromCatalogEntryId(Catalog, 998 CatalogEntryId, 999 &CatalogEntry); 1000 } 1001 else 1002 { 1003 /* Get it from the address family */ 1004 ErrorCode = WsTcGetEntryFromAf(Catalog, AddressFamily, &CatalogEntry); 1005 } 1006 1007 /* Check for success */ 1008 if (ErrorCode == ERROR_SUCCESS) 1009 { 1010 /* Call the provider */ 1011 Status = CatalogEntry->Provider->Service.lpWSPStringToAddress(AddressString, 1012 AddressFamily, 1013 &CatalogEntry-> 1014 ProtocolInfo, 1015 lpAddress, 1016 lpAddressLength, 1017 &ErrorCode); 1018 1019 /* Dereference the entry */ 1020 WsTcEntryDereference(CatalogEntry); 1021 1022 /* Check for success and return */ 1023 if (Status == ERROR_SUCCESS) return ERROR_SUCCESS; 1024 } 1025 1026 /* Set the error and return */ 1027 SetLastError(ErrorCode); 1028 return SOCKET_ERROR; 1029 } 1030