1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS WinSock Helper DLL for TCP/IP 4 * FILE: wshtcpip.c 5 * PURPOSE: DLL entry 6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) 7 * REVISIONS: 8 * CSH 01/09-2000 Created 9 */ 10 #include "wshtcpip.h" 11 #define NDEBUG 12 #include <debug.h> 13 14 BOOL 15 EXPORT 16 DllMain(HANDLE hInstDll, 17 ULONG dwReason, 18 PVOID Reserved) 19 { 20 DPRINT("DllMain of wshtcpip.dll\n"); 21 22 switch (dwReason) { 23 case DLL_PROCESS_ATTACH: 24 /* Don't need thread attach notifications 25 so disable them to improve performance */ 26 DisableThreadLibraryCalls(hInstDll); 27 break; 28 29 case DLL_THREAD_ATTACH: 30 break; 31 32 case DLL_THREAD_DETACH: 33 break; 34 35 case DLL_PROCESS_DETACH: 36 break; 37 } 38 return TRUE; 39 } 40 41 42 INT 43 EXPORT 44 WSHAddressToString( 45 IN LPSOCKADDR Address, 46 IN INT AddressLength, 47 IN LPWSAPROTOCOL_INFOW ProtocolInfo OPTIONAL, 48 OUT LPWSTR AddressString, 49 IN OUT LPDWORD AddressStringLength) 50 { 51 UNIMPLEMENTED; 52 53 return NO_ERROR; 54 } 55 56 57 INT 58 EXPORT 59 WSHEnumProtocols( 60 IN LPINT lpiProtocols OPTIONAL, 61 IN LPWSTR lpTransportKeyName, 62 IN OUT LPVOID lpProtocolBuffer, 63 IN OUT LPDWORD lpdwBufferLength) 64 { 65 UNIMPLEMENTED; 66 67 return NO_ERROR; 68 } 69 70 71 INT 72 EXPORT 73 WSHGetBroadcastSockaddr( 74 IN PVOID HelperDllSocketContext, 75 OUT PSOCKADDR Sockaddr, 76 OUT PINT SockaddrLength) 77 { 78 INT Size = 2 * sizeof(UINT); 79 80 if (*SockaddrLength < Size) 81 { 82 DPRINT1("Socket address length too small: %d\n", *SockaddrLength); 83 return WSAEFAULT; 84 } 85 86 RtlZeroMemory(Sockaddr, *SockaddrLength); 87 88 Sockaddr->sa_family = AF_INET; 89 *((PUINT)Sockaddr->sa_data) = INADDR_BROADCAST; 90 91 /* *SockaddrLength = Size; */ 92 93 return NO_ERROR; 94 } 95 96 97 INT 98 EXPORT 99 WSHGetProviderGuid( 100 IN LPWSTR ProviderName, 101 OUT LPGUID ProviderGuid) 102 { 103 UNIMPLEMENTED; 104 105 return NO_ERROR; 106 } 107 108 109 /* 110 Document from OSR how WSHGetSockaddrType works 111 http://www.osronline.com/ddkx/network/37wshfun_5lyq.htm 112 */ 113 114 INT 115 EXPORT 116 WSHGetSockaddrType( 117 IN PSOCKADDR Sockaddr, 118 IN DWORD SockaddrLength, 119 OUT PSOCKADDR_INFO SockaddrInfo) 120 { 121 PSOCKADDR_IN ipv4 = (PSOCKADDR_IN)Sockaddr; 122 123 if (!ipv4 || !SockaddrInfo || SockaddrLength < sizeof(SOCKADDR_IN) || 124 ipv4->sin_family != AF_INET) 125 { 126 DPRINT1("Invalid parameter: %x %x %d %u\n", ipv4, SockaddrInfo, SockaddrLength, (ipv4 ? ipv4->sin_family : 0)); 127 return WSAEINVAL; 128 } 129 130 switch (ntohl(ipv4->sin_addr.s_addr)) 131 { 132 case INADDR_ANY: 133 SockaddrInfo->AddressInfo = SockaddrAddressInfoWildcard; 134 break; 135 136 case INADDR_BROADCAST: 137 SockaddrInfo->AddressInfo = SockaddrAddressInfoBroadcast; 138 break; 139 140 case INADDR_LOOPBACK: 141 SockaddrInfo->AddressInfo = SockaddrAddressInfoLoopback; 142 break; 143 144 default: 145 SockaddrInfo->AddressInfo = SockaddrAddressInfoNormal; 146 break; 147 } 148 149 if (ntohs(ipv4->sin_port) == 0) 150 SockaddrInfo->EndpointInfo = SockaddrEndpointInfoWildcard; 151 else if (ntohs(ipv4->sin_port) < IPPORT_RESERVED) 152 SockaddrInfo->EndpointInfo = SockaddrEndpointInfoReserved; 153 else 154 SockaddrInfo->EndpointInfo = SockaddrEndpointInfoNormal; 155 156 return NO_ERROR; 157 } 158 159 static 160 void 161 GetTdiTypeId( 162 _In_ INT Level, 163 _In_ INT OptionName, 164 _Out_ PULONG TdiType, 165 _Out_ PULONG TdiId) 166 { 167 switch (Level) 168 { 169 case SOL_SOCKET: 170 *TdiType = INFO_TYPE_ADDRESS_OBJECT; 171 switch (OptionName) 172 { 173 case SO_KEEPALIVE: 174 /* FIXME: Return proper option */ 175 ASSERT(FALSE); 176 break; 177 default: 178 break; 179 } 180 break; 181 182 case IPPROTO_IP: 183 *TdiType = INFO_TYPE_ADDRESS_OBJECT; 184 switch (OptionName) 185 { 186 case IP_TTL: 187 *TdiId = AO_OPTION_TTL; 188 return; 189 190 case IP_DONTFRAGMENT: 191 *TdiId = AO_OPTION_IP_DONTFRAGMENT; 192 return; 193 194 #if 0 195 case IP_RECEIVE_BROADCAST: 196 *TdiId = AO_OPTION_BROADCAST; 197 return; 198 #endif 199 200 case IP_HDRINCL: 201 *TdiId = AO_OPTION_IP_HDRINCL; 202 return; 203 204 default: 205 break; 206 } 207 break; 208 209 case IPPROTO_TCP: 210 *TdiType = INFO_TYPE_CONNECTION; 211 switch (OptionName) 212 { 213 case TCP_NODELAY: 214 *TdiId = TCP_SOCKET_NODELAY; 215 return; 216 default: 217 break; 218 } 219 220 default: 221 break; 222 } 223 224 DPRINT1("Unknown level/option name: %d %d\n", Level, OptionName); 225 *TdiType = 0; 226 *TdiId = 0; 227 } 228 229 INT 230 EXPORT 231 WSHGetSocketInformation( 232 IN PVOID HelperDllSocketContext, 233 IN SOCKET SocketHandle, 234 IN HANDLE TdiAddressObjectHandle, 235 IN HANDLE TdiConnectionObjectHandle, 236 IN INT Level, 237 IN INT OptionName, 238 OUT PCHAR OptionValue, 239 OUT LPINT OptionLength) 240 { 241 UNIMPLEMENTED; 242 243 DPRINT1("Get: Unknown level/option name: %d %d\n", Level, OptionName); 244 245 *OptionLength = 0; 246 247 return NO_ERROR; 248 } 249 250 251 INT 252 EXPORT 253 WSHGetWildcardSockaddr( 254 IN PVOID HelperDllSocketContext, 255 OUT PSOCKADDR Sockaddr, 256 OUT PINT SockaddrLength) 257 { 258 INT Size = 2 * sizeof(UINT); 259 260 if (*SockaddrLength < Size) 261 { 262 DPRINT1("Socket address length too small: %d\n", *SockaddrLength); 263 return WSAEFAULT; 264 } 265 266 RtlZeroMemory(Sockaddr, *SockaddrLength); 267 268 Sockaddr->sa_family = AF_INET; 269 *((PUINT)Sockaddr->sa_data) = INADDR_ANY; 270 271 /* *SockaddrLength = Size; */ 272 273 return NO_ERROR; 274 } 275 276 277 DWORD 278 EXPORT 279 WSHGetWinsockMapping( 280 OUT PWINSOCK_MAPPING Mapping, 281 IN DWORD MappingLength) 282 { 283 DWORD Rows = 6; 284 DWORD Columns = 3; 285 DWORD Size = 2 * sizeof(DWORD) + Columns * Rows * sizeof(DWORD); 286 287 if (MappingLength < Size) 288 { 289 DPRINT1("Mapping length too small: %d\n", MappingLength); 290 return Size; 291 } 292 293 Mapping->Rows = Rows; 294 Mapping->Columns = Columns; 295 296 Mapping->Mapping[0].AddressFamily = AF_INET; 297 Mapping->Mapping[0].SocketType = SOCK_STREAM; 298 Mapping->Mapping[0].Protocol = 0; 299 300 Mapping->Mapping[1].AddressFamily = AF_INET; 301 Mapping->Mapping[1].SocketType = SOCK_STREAM; 302 Mapping->Mapping[1].Protocol = IPPROTO_TCP; 303 304 Mapping->Mapping[2].AddressFamily = AF_INET; 305 Mapping->Mapping[2].SocketType = SOCK_DGRAM; 306 Mapping->Mapping[2].Protocol = 0; 307 308 Mapping->Mapping[3].AddressFamily = AF_INET; 309 Mapping->Mapping[3].SocketType = SOCK_DGRAM; 310 Mapping->Mapping[3].Protocol = IPPROTO_UDP; 311 312 Mapping->Mapping[4].AddressFamily = AF_INET; 313 Mapping->Mapping[4].SocketType = SOCK_RAW; 314 Mapping->Mapping[4].Protocol = 0; 315 316 Mapping->Mapping[5].AddressFamily = AF_INET; 317 Mapping->Mapping[5].SocketType = SOCK_RAW; 318 Mapping->Mapping[5].Protocol = IPPROTO_ICMP; 319 320 return NO_ERROR; 321 } 322 323 324 INT 325 EXPORT 326 WSHGetWSAProtocolInfo( 327 IN LPWSTR ProviderName, 328 OUT LPWSAPROTOCOL_INFOW *ProtocolInfo, 329 OUT LPDWORD ProtocolInfoEntries) 330 { 331 UNIMPLEMENTED; 332 333 return NO_ERROR; 334 } 335 336 337 INT 338 EXPORT 339 WSHIoctl( 340 IN PVOID HelperDllSocketContext, 341 IN SOCKET SocketHandle, 342 IN HANDLE TdiAddressObjectHandle, 343 IN HANDLE TdiConnectionObjectHandle, 344 IN DWORD IoControlCode, 345 IN LPVOID InputBuffer, 346 IN DWORD InputBufferLength, 347 IN LPVOID OutputBuffer, 348 IN DWORD OutputBufferLength, 349 OUT LPDWORD NumberOfBytesReturned, 350 IN LPWSAOVERLAPPED Overlapped, 351 IN LPWSAOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine, 352 OUT LPBOOL NeedsCompletion) 353 { 354 INT res; 355 356 if (IoControlCode == SIO_GET_INTERFACE_LIST) 357 { 358 res = WSHIoctl_GetInterfaceList( 359 OutputBuffer, 360 OutputBufferLength, 361 NumberOfBytesReturned, 362 NeedsCompletion); 363 return res; 364 } 365 366 UNIMPLEMENTED; 367 368 DPRINT1("Ioctl: Unknown IOCTL code: %x\n", IoControlCode); 369 370 return WSAEINVAL; 371 } 372 373 374 INT 375 EXPORT 376 WSHJoinLeaf( 377 IN PVOID HelperDllSocketContext, 378 IN SOCKET SocketHandle, 379 IN HANDLE TdiAddressObjectHandle, 380 IN HANDLE TdiConnectionObjectHandle, 381 IN PVOID LeafHelperDllSocketContext, 382 IN SOCKET LeafSocketHandle, 383 IN PSOCKADDR Sockaddr, 384 IN DWORD SockaddrLength, 385 IN LPWSABUF CallerData, 386 IN LPWSABUF CalleeData, 387 IN LPQOS SocketQOS, 388 IN LPQOS GroupQOS, 389 IN DWORD Flags) 390 { 391 UNIMPLEMENTED; 392 393 return NO_ERROR; 394 } 395 396 INT 397 SendRequest( 398 IN PVOID Request, 399 IN DWORD RequestSize, 400 IN DWORD IOCTL) 401 { 402 BOOLEAN Success; 403 HANDLE TcpCC; 404 DWORD BytesReturned; 405 406 if (openTcpFile(&TcpCC, FILE_READ_DATA | FILE_WRITE_DATA) != STATUS_SUCCESS) 407 return WSAEINVAL; 408 409 Success = DeviceIoControl(TcpCC, 410 IOCTL, 411 Request, 412 RequestSize, 413 NULL, 414 0, 415 &BytesReturned, 416 NULL); 417 418 closeTcpFile(TcpCC); 419 420 DPRINT("DeviceIoControl: %ld\n", ((Success != FALSE) ? 0 : GetLastError())); 421 422 if (!Success) 423 return WSAEINVAL; 424 425 return NO_ERROR; 426 } 427 428 INT 429 EXPORT 430 WSHNotify( 431 IN PVOID HelperDllSocketContext, 432 IN SOCKET SocketHandle, 433 IN HANDLE TdiAddressObjectHandle, 434 IN HANDLE TdiConnectionObjectHandle, 435 IN DWORD NotifyEvent) 436 { 437 PSOCKET_CONTEXT Context = HelperDllSocketContext; 438 NTSTATUS Status; 439 HANDLE TcpCC; 440 TDIEntityID *EntityIDs; 441 DWORD EntityCount, i; 442 PQUEUED_REQUEST QueuedRequest, NextQueuedRequest; 443 444 switch (NotifyEvent) 445 { 446 case WSH_NOTIFY_CLOSE: 447 DPRINT("WSHNotify: WSH_NOTIFY_CLOSE\n"); 448 QueuedRequest = Context->RequestQueue; 449 while (QueuedRequest) 450 { 451 NextQueuedRequest = QueuedRequest->Next; 452 453 HeapFree(GetProcessHeap(), 0, QueuedRequest->Info); 454 HeapFree(GetProcessHeap(), 0, QueuedRequest); 455 456 QueuedRequest = NextQueuedRequest; 457 } 458 HeapFree(GetProcessHeap(), 0, HelperDllSocketContext); 459 break; 460 461 462 case WSH_NOTIFY_BIND: 463 DPRINT("WSHNotify: WSH_NOTIFY_BIND\n"); 464 Status = openTcpFile(&TcpCC, FILE_READ_DATA); 465 if (Status != STATUS_SUCCESS) 466 return WSAEINVAL; 467 468 Status = tdiGetEntityIDSet(TcpCC, 469 &EntityIDs, 470 &EntityCount); 471 472 closeTcpFile(TcpCC); 473 474 if (Status != STATUS_SUCCESS) 475 return WSAEINVAL; 476 477 for (i = 0; i < EntityCount; i++) 478 { 479 if (EntityIDs[i].tei_entity == CO_TL_ENTITY || 480 EntityIDs[i].tei_entity == CL_TL_ENTITY || 481 EntityIDs[i].tei_entity == ER_ENTITY) 482 { 483 Context->AddrFileInstance = EntityIDs[i].tei_instance; 484 Context->AddrFileEntityType = EntityIDs[i].tei_entity; 485 } 486 } 487 488 DPRINT("Instance: %lx Type: %lx\n", Context->AddrFileInstance, Context->AddrFileEntityType); 489 490 tdiFreeThingSet(EntityIDs); 491 492 Context->SocketState = SocketStateBound; 493 494 QueuedRequest = Context->RequestQueue; 495 while (QueuedRequest) 496 { 497 QueuedRequest->Info->ID.toi_entity.tei_entity = Context->AddrFileEntityType; 498 QueuedRequest->Info->ID.toi_entity.tei_instance = Context->AddrFileInstance; 499 500 SendRequest(QueuedRequest->Info, 501 sizeof(*QueuedRequest->Info) + QueuedRequest->Info->BufferSize, 502 IOCTL_TCP_SET_INFORMATION_EX); 503 504 NextQueuedRequest = QueuedRequest->Next; 505 506 HeapFree(GetProcessHeap(), 0, QueuedRequest->Info); 507 HeapFree(GetProcessHeap(), 0, QueuedRequest); 508 509 QueuedRequest = NextQueuedRequest; 510 } 511 Context->RequestQueue = NULL; 512 break; 513 514 default: 515 DPRINT1("Unwanted notification received! (%ld)\n", NotifyEvent); 516 break; 517 } 518 519 return NO_ERROR; 520 } 521 522 523 INT 524 EXPORT 525 WSHOpenSocket( 526 IN OUT PINT AddressFamily, 527 IN OUT PINT SocketType, 528 IN OUT PINT Protocol, 529 OUT PUNICODE_STRING TransportDeviceName, 530 OUT PVOID HelperDllSocketContext, 531 OUT PDWORD NotificationEvents) 532 /* 533 * FUNCTION: Opens a socket 534 */ 535 { 536 return WSHOpenSocket2(AddressFamily, 537 SocketType, 538 Protocol, 539 0, 540 0, 541 TransportDeviceName, 542 HelperDllSocketContext, 543 NotificationEvents); 544 } 545 546 547 INT 548 EXPORT 549 WSHOpenSocket2( 550 OUT PINT AddressFamily, 551 IN OUT PINT SocketType, 552 IN OUT PINT Protocol, 553 IN GROUP Group, 554 IN DWORD Flags, 555 OUT PUNICODE_STRING TransportDeviceName, 556 OUT PVOID *HelperDllSocketContext, 557 OUT PDWORD NotificationEvents) 558 /* 559 * FUNCTION: Opens a socket 560 * ARGUMENTS: 561 * AddressFamily = Address of buffer with address family (updated) 562 * SocketType = Address of buffer with type of socket (updated) 563 * Protocol = Address of buffer with protocol number (updated) 564 * Group = Socket group 565 * Flags = Socket flags 566 * TransportDeviceName = Address of buffer to place name of transport device 567 * HelperDllSocketContext = Address of buffer to place socket context pointer 568 * NotificationEvents = Address of buffer to place flags for event notification 569 * RETURNS: 570 * Status of operation 571 * NOTES: 572 * Mapping tripple is returned in an canonicalized form 573 */ 574 { 575 PSOCKET_CONTEXT Context; 576 UNICODE_STRING String; 577 UNICODE_STRING TcpDeviceName = RTL_CONSTANT_STRING(DD_TCP_DEVICE_NAME); 578 UNICODE_STRING UdpDeviceName = RTL_CONSTANT_STRING(DD_UDP_DEVICE_NAME); 579 UNICODE_STRING RawDeviceName = RTL_CONSTANT_STRING(DD_RAW_IP_DEVICE_NAME); 580 581 DPRINT("WSHOpenSocket2 called\n"); 582 583 switch (*SocketType) { 584 case SOCK_STREAM: 585 String = TcpDeviceName; 586 break; 587 588 case SOCK_DGRAM: 589 String = UdpDeviceName; 590 break; 591 592 case SOCK_RAW: 593 if ((*Protocol < 0) || (*Protocol > 255)) 594 return WSAEINVAL; 595 596 String = RawDeviceName; 597 break; 598 599 default: 600 return WSAEINVAL; 601 } 602 603 RtlInitUnicodeString(TransportDeviceName, NULL); 604 605 TransportDeviceName->MaximumLength = String.Length + /* Transport device name */ 606 (4 * sizeof(WCHAR) + /* Separator and protocol */ 607 sizeof(UNICODE_NULL)); /* Terminating null */ 608 609 TransportDeviceName->Buffer = HeapAlloc( 610 GetProcessHeap(), 611 0, 612 TransportDeviceName->MaximumLength); 613 614 if (!TransportDeviceName->Buffer) 615 return WSAENOBUFS; 616 617 /* Append the transport device name */ 618 RtlAppendUnicodeStringToString(TransportDeviceName, &String); 619 620 if (*SocketType == SOCK_RAW) { 621 /* Append a separator */ 622 TransportDeviceName->Buffer[TransportDeviceName->Length / sizeof(WCHAR)] = OBJ_NAME_PATH_SEPARATOR; 623 TransportDeviceName->Length += sizeof(WCHAR); 624 TransportDeviceName->Buffer[TransportDeviceName->Length / sizeof(WCHAR)] = UNICODE_NULL; 625 626 /* Append the protocol number */ 627 String.Buffer = TransportDeviceName->Buffer + (TransportDeviceName->Length / sizeof(WCHAR)); 628 String.Length = 0; 629 String.MaximumLength = TransportDeviceName->MaximumLength - TransportDeviceName->Length; 630 631 RtlIntegerToUnicodeString((ULONG)*Protocol, 10, &String); 632 633 TransportDeviceName->Length += String.Length; 634 } 635 636 /* Setup a socket context area */ 637 638 Context = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SOCKET_CONTEXT)); 639 if (!Context) { 640 RtlFreeUnicodeString(TransportDeviceName); 641 return WSAENOBUFS; 642 } 643 644 Context->AddressFamily = *AddressFamily; 645 Context->SocketType = *SocketType; 646 Context->Protocol = *Protocol; 647 Context->Flags = Flags; 648 Context->SocketState = SocketStateCreated; 649 650 *HelperDllSocketContext = Context; 651 *NotificationEvents = WSH_NOTIFY_CLOSE | WSH_NOTIFY_BIND; 652 653 return NO_ERROR; 654 } 655 656 INT 657 EXPORT 658 WSHSetSocketInformation( 659 IN PVOID HelperDllSocketContext, 660 IN SOCKET SocketHandle, 661 IN HANDLE TdiAddressObjectHandle, 662 IN HANDLE TdiConnectionObjectHandle, 663 IN INT Level, 664 IN INT OptionName, 665 IN PCHAR OptionValue, 666 IN INT OptionLength) 667 { 668 PSOCKET_CONTEXT Context = HelperDllSocketContext; 669 ULONG TdiType, TdiId; 670 INT Status; 671 PTCP_REQUEST_SET_INFORMATION_EX Info; 672 PQUEUED_REQUEST Queued, NextQueued; 673 674 DPRINT("WSHSetSocketInformation\n"); 675 676 /* FIXME: We only handle address file object here */ 677 678 switch (Level) 679 { 680 case SOL_SOCKET: 681 switch (OptionName) 682 { 683 case SO_DONTROUTE: 684 if (OptionLength < sizeof(BOOL)) 685 { 686 return WSAEFAULT; 687 } 688 Context->DontRoute = *(BOOL*)OptionValue; 689 /* This is silently ignored on Windows */ 690 return 0; 691 692 case SO_KEEPALIVE: 693 /* FIXME -- We'll send this to TCPIP */ 694 DPRINT1("Set: SO_KEEPALIVE not yet supported\n"); 695 return 0; 696 697 default: 698 /* Invalid option */ 699 DPRINT1("Set: Received unexpected SOL_SOCKET option %d\n", OptionName); 700 return WSAENOPROTOOPT; 701 } 702 break; 703 704 case IPPROTO_IP: 705 switch (OptionName) 706 { 707 case IP_TTL: 708 case IP_DONTFRAGMENT: 709 case IP_HDRINCL: 710 /* Send these to TCPIP */ 711 break; 712 713 default: 714 /* Invalid option -- FIXME */ 715 DPRINT1("Set: Received unsupported IPPROTO_IP option %d\n", OptionName); 716 return 0; 717 } 718 break; 719 720 case IPPROTO_TCP: 721 switch (OptionName) 722 { 723 case TCP_NODELAY: 724 if (OptionLength < sizeof(CHAR)) 725 { 726 return WSAEFAULT; 727 } 728 break; 729 730 default: 731 /* Invalid option */ 732 DPRINT1("Set: Received unexpected IPPROTO_TCP option %d\n", OptionName); 733 return 0; 734 } 735 break; 736 737 default: 738 DPRINT1("Set: Received unexpected %d option %d\n", Level, OptionName); 739 return 0; 740 } 741 742 /* If we get here, GetAddressOption must return something valid */ 743 GetTdiTypeId(Level, OptionName, &TdiType, &TdiId); 744 ASSERT((TdiId != 0) && (TdiType != 0)); 745 746 Info = HeapAlloc(GetProcessHeap(), 0, sizeof(*Info) + OptionLength); 747 if (!Info) 748 return WSAENOBUFS; 749 750 Info->ID.toi_entity.tei_entity = Context->AddrFileEntityType; 751 Info->ID.toi_entity.tei_instance = Context->AddrFileInstance; 752 Info->ID.toi_class = INFO_CLASS_PROTOCOL; 753 Info->ID.toi_type = TdiType; 754 Info->ID.toi_id = TdiId; 755 Info->BufferSize = OptionLength; 756 memcpy(Info->Buffer, OptionValue, OptionLength); 757 758 if (Context->SocketState == SocketStateCreated) 759 { 760 if (Context->RequestQueue) 761 { 762 Queued = Context->RequestQueue; 763 while ((NextQueued = Queued->Next)) 764 { 765 Queued = NextQueued; 766 } 767 768 Queued->Next = HeapAlloc(GetProcessHeap(), 0, sizeof(QUEUED_REQUEST)); 769 if (!Queued->Next) 770 { 771 HeapFree(GetProcessHeap(), 0, Info); 772 return WSAENOBUFS; 773 } 774 775 NextQueued = Queued->Next; 776 NextQueued->Next = NULL; 777 NextQueued->Info = Info; 778 } 779 else 780 { 781 Context->RequestQueue = HeapAlloc(GetProcessHeap(), 0, sizeof(QUEUED_REQUEST)); 782 if (!Context->RequestQueue) 783 { 784 HeapFree(GetProcessHeap(), 0, Info); 785 return WSAENOBUFS; 786 } 787 788 Context->RequestQueue->Next = NULL; 789 Context->RequestQueue->Info = Info; 790 } 791 792 return 0; 793 } 794 795 Status = SendRequest(Info, sizeof(*Info) + Info->BufferSize, IOCTL_TCP_SET_INFORMATION_EX); 796 797 HeapFree(GetProcessHeap(), 0, Info); 798 799 return Status; 800 } 801 802 803 INT 804 EXPORT 805 WSHStringToAddress( 806 IN LPWSTR AddressString, 807 IN DWORD AddressFamily, 808 IN LPWSAPROTOCOL_INFOW ProtocolInfo OPTIONAL, 809 OUT LPSOCKADDR Address, 810 IN OUT LPDWORD AddressStringLength) 811 { 812 UNIMPLEMENTED; 813 814 return NO_ERROR; 815 } 816 817 /* EOF */ 818