1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Ancillary Function Driver DLL 4 * FILE: dll/win32/msafd/misc/dllmain.c 5 * PURPOSE: DLL entry point 6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) 7 * Alex Ionescu (alex@relsoft.net) 8 * Pierre Schweitzer (pierre@reactos.org) 9 * REVISIONS: 10 * CSH 01/09-2000 Created 11 * Alex 16/07/2004 - Complete Rewrite 12 */ 13 14 #include <msafd.h> 15 16 #include <winuser.h> 17 #include <wchar.h> 18 19 HANDLE GlobalHeap; 20 WSPUPCALLTABLE Upcalls; 21 DWORD CatalogEntryId; /* CatalogEntryId for upcalls */ 22 LPWPUCOMPLETEOVERLAPPEDREQUEST lpWPUCompleteOverlappedRequest; 23 PSOCKET_INFORMATION SocketListHead = NULL; 24 CRITICAL_SECTION SocketListLock; 25 LIST_ENTRY SockHelpersListHead = { NULL, NULL }; 26 ULONG SockAsyncThreadRefCount; 27 HANDLE SockAsyncHelperAfdHandle; 28 HANDLE SockAsyncCompletionPort = NULL; 29 BOOLEAN SockAsyncSelectCalled; 30 31 32 33 /* 34 * FUNCTION: Creates a new socket 35 * ARGUMENTS: 36 * af = Address family 37 * type = Socket type 38 * protocol = Protocol type 39 * lpProtocolInfo = Pointer to protocol information 40 * g = Reserved 41 * dwFlags = Socket flags 42 * lpErrno = Address of buffer for error information 43 * RETURNS: 44 * Created socket, or INVALID_SOCKET if it could not be created 45 */ 46 SOCKET 47 WSPAPI 48 WSPSocket(int AddressFamily, 49 int SocketType, 50 int Protocol, 51 LPWSAPROTOCOL_INFOW lpProtocolInfo, 52 GROUP g, 53 DWORD dwFlags, 54 LPINT lpErrno) 55 { 56 OBJECT_ATTRIBUTES Object; 57 IO_STATUS_BLOCK IOSB; 58 USHORT SizeOfPacket; 59 ULONG SizeOfEA; 60 PAFD_CREATE_PACKET AfdPacket; 61 HANDLE Sock; 62 PSOCKET_INFORMATION Socket = NULL; 63 PFILE_FULL_EA_INFORMATION EABuffer = NULL; 64 PHELPER_DATA HelperData; 65 PVOID HelperDLLContext; 66 DWORD HelperEvents; 67 UNICODE_STRING TransportName; 68 UNICODE_STRING DevName; 69 LARGE_INTEGER GroupData; 70 INT Status; 71 PSOCK_SHARED_INFO SharedData = NULL; 72 73 TRACE("Creating Socket, getting TDI Name - AddressFamily (%d) SocketType (%d) Protocol (%d).\n", 74 AddressFamily, SocketType, Protocol); 75 76 if (lpProtocolInfo && lpProtocolInfo->dwServiceFlags3 != 0 && lpProtocolInfo->dwServiceFlags4 != 0) 77 { 78 /* Duplpicating socket from different process */ 79 if (UlongToPtr(lpProtocolInfo->dwServiceFlags3) == INVALID_HANDLE_VALUE) 80 { 81 Status = WSAEINVAL; 82 goto error; 83 } 84 if (UlongToPtr(lpProtocolInfo->dwServiceFlags4) == INVALID_HANDLE_VALUE) 85 { 86 Status = WSAEINVAL; 87 goto error; 88 } 89 SharedData = MapViewOfFile(UlongToPtr(lpProtocolInfo->dwServiceFlags3), 90 FILE_MAP_ALL_ACCESS, 91 0, 92 0, 93 sizeof(SOCK_SHARED_INFO)); 94 if (!SharedData) 95 { 96 Status = WSAEINVAL; 97 goto error; 98 } 99 InterlockedIncrement(&SharedData->RefCount); 100 AddressFamily = SharedData->AddressFamily; 101 SocketType = SharedData->SocketType; 102 Protocol = SharedData->Protocol; 103 } 104 105 if (AddressFamily == AF_UNSPEC && SocketType == 0 && Protocol == 0) 106 { 107 Status = WSAEINVAL; 108 goto error; 109 } 110 111 /* Set the defaults */ 112 if (AddressFamily == AF_UNSPEC) 113 AddressFamily = AF_INET; 114 115 if (SocketType == 0) 116 { 117 switch (Protocol) 118 { 119 case IPPROTO_TCP: 120 SocketType = SOCK_STREAM; 121 break; 122 case IPPROTO_UDP: 123 SocketType = SOCK_DGRAM; 124 break; 125 case IPPROTO_RAW: 126 SocketType = SOCK_RAW; 127 break; 128 default: 129 TRACE("Unknown Protocol (%d). We will try SOCK_STREAM.\n", Protocol); 130 SocketType = SOCK_STREAM; 131 break; 132 } 133 } 134 135 if (Protocol == 0) 136 { 137 switch (SocketType) 138 { 139 case SOCK_STREAM: 140 Protocol = IPPROTO_TCP; 141 break; 142 case SOCK_DGRAM: 143 Protocol = IPPROTO_UDP; 144 break; 145 case SOCK_RAW: 146 Protocol = IPPROTO_RAW; 147 break; 148 default: 149 TRACE("Unknown SocketType (%d). We will try IPPROTO_TCP.\n", SocketType); 150 Protocol = IPPROTO_TCP; 151 break; 152 } 153 } 154 155 /* Get Helper Data and Transport */ 156 Status = SockGetTdiName (&AddressFamily, 157 &SocketType, 158 &Protocol, 159 g, 160 dwFlags, 161 &TransportName, 162 &HelperDLLContext, 163 &HelperData, 164 &HelperEvents); 165 166 /* Check for error */ 167 if (Status != NO_ERROR) 168 { 169 ERR("SockGetTdiName: Status %x\n", Status); 170 goto error; 171 } 172 173 /* AFD Device Name */ 174 RtlInitUnicodeString(&DevName, L"\\Device\\Afd\\Endpoint"); 175 176 /* Set Socket Data */ 177 Socket = HeapAlloc(GlobalHeap, 0, sizeof(*Socket)); 178 if (!Socket) 179 { 180 Status = WSAENOBUFS; 181 goto error; 182 } 183 RtlZeroMemory(Socket, sizeof(*Socket)); 184 if (SharedData) 185 { 186 Socket->SharedData = SharedData; 187 Socket->SharedDataHandle = UlongToHandle(lpProtocolInfo->dwServiceFlags3); 188 Sock = UlongToHandle(lpProtocolInfo->dwServiceFlags4); 189 Socket->Handle = (SOCKET)lpProtocolInfo->dwServiceFlags4; 190 } 191 else 192 { 193 Socket->SharedDataHandle = INVALID_HANDLE_VALUE; 194 Socket->SharedData = HeapAlloc(GlobalHeap, 0, sizeof(*Socket->SharedData)); 195 if (!Socket->SharedData) 196 { 197 Status = WSAENOBUFS; 198 goto error; 199 } 200 RtlZeroMemory(Socket->SharedData, sizeof(*Socket->SharedData)); 201 Socket->SharedData->State = SocketOpen; 202 Socket->SharedData->RefCount = 1L; 203 Socket->SharedData->Listening = FALSE; 204 Socket->SharedData->AddressFamily = AddressFamily; 205 Socket->SharedData->SocketType = SocketType; 206 Socket->SharedData->Protocol = Protocol; 207 Socket->SharedData->SizeOfLocalAddress = HelperData->MaxWSAddressLength; 208 Socket->SharedData->SizeOfRemoteAddress = HelperData->MaxWSAddressLength; 209 Socket->SharedData->UseDelayedAcceptance = HelperData->UseDelayedAcceptance; 210 Socket->SharedData->CreateFlags = dwFlags; 211 Socket->SharedData->ServiceFlags1 = lpProtocolInfo->dwServiceFlags1; 212 Socket->SharedData->ProviderFlags = lpProtocolInfo->dwProviderFlags; 213 Socket->SharedData->UseSAN = FALSE; 214 Socket->SharedData->NonBlocking = FALSE; /* Sockets start blocking */ 215 Socket->SharedData->RecvTimeout = INFINITE; 216 Socket->SharedData->SendTimeout = INFINITE; 217 Socket->SharedData->OobInline = FALSE; 218 219 /* Ask alex about this */ 220 if( Socket->SharedData->SocketType == SOCK_DGRAM || 221 Socket->SharedData->SocketType == SOCK_RAW ) 222 { 223 TRACE("Connectionless socket\n"); 224 Socket->SharedData->ServiceFlags1 |= XP1_CONNECTIONLESS; 225 } 226 Socket->Handle = INVALID_SOCKET; 227 } 228 229 Socket->HelperContext = HelperDLLContext; 230 Socket->HelperData = HelperData; 231 Socket->HelperEvents = HelperEvents; 232 Socket->LocalAddress = &Socket->SharedData->WSLocalAddress; 233 Socket->RemoteAddress = &Socket->SharedData->WSRemoteAddress; 234 Socket->SanData = NULL; 235 RtlCopyMemory(&Socket->ProtocolInfo, lpProtocolInfo, sizeof(Socket->ProtocolInfo)); 236 if (SharedData) 237 goto ok; 238 239 /* Packet Size */ 240 SizeOfPacket = TransportName.Length + sizeof(AFD_CREATE_PACKET) + sizeof(WCHAR); 241 242 /* EA Size */ 243 SizeOfEA = SizeOfPacket + sizeof(FILE_FULL_EA_INFORMATION) + AFD_PACKET_COMMAND_LENGTH; 244 245 /* Set up EA Buffer */ 246 EABuffer = HeapAlloc(GlobalHeap, 0, SizeOfEA); 247 if (!EABuffer) 248 { 249 Status = WSAENOBUFS; 250 goto error; 251 } 252 253 RtlZeroMemory(EABuffer, SizeOfEA); 254 EABuffer->NextEntryOffset = 0; 255 EABuffer->Flags = 0; 256 EABuffer->EaNameLength = AFD_PACKET_COMMAND_LENGTH; 257 RtlCopyMemory (EABuffer->EaName, 258 AfdCommand, 259 AFD_PACKET_COMMAND_LENGTH + 1); 260 EABuffer->EaValueLength = SizeOfPacket; 261 262 /* Set up AFD Packet */ 263 AfdPacket = (PAFD_CREATE_PACKET)(EABuffer->EaName + EABuffer->EaNameLength + 1); 264 AfdPacket->SizeOfTransportName = TransportName.Length; 265 RtlCopyMemory (AfdPacket->TransportName, 266 TransportName.Buffer, 267 TransportName.Length + sizeof(WCHAR)); 268 AfdPacket->GroupID = g; 269 270 /* Set up Endpoint Flags */ 271 if ((Socket->SharedData->ServiceFlags1 & XP1_CONNECTIONLESS) != 0) 272 { 273 if ((SocketType != SOCK_DGRAM) && (SocketType != SOCK_RAW)) 274 { 275 /* Only RAW or UDP can be Connectionless */ 276 Status = WSAEINVAL; 277 goto error; 278 } 279 AfdPacket->EndpointFlags |= AFD_ENDPOINT_CONNECTIONLESS; 280 } 281 282 if ((Socket->SharedData->ServiceFlags1 & XP1_MESSAGE_ORIENTED) != 0) 283 { 284 if (SocketType == SOCK_STREAM) 285 { 286 if ((Socket->SharedData->ServiceFlags1 & XP1_PSEUDO_STREAM) == 0) 287 { 288 /* The Provider doesn't actually support Message Oriented Streams */ 289 Status = WSAEINVAL; 290 goto error; 291 } 292 } 293 AfdPacket->EndpointFlags |= AFD_ENDPOINT_MESSAGE_ORIENTED; 294 } 295 296 if (SocketType == SOCK_RAW) AfdPacket->EndpointFlags |= AFD_ENDPOINT_RAW; 297 298 if (dwFlags & (WSA_FLAG_MULTIPOINT_C_ROOT | 299 WSA_FLAG_MULTIPOINT_C_LEAF | 300 WSA_FLAG_MULTIPOINT_D_ROOT | 301 WSA_FLAG_MULTIPOINT_D_LEAF)) 302 { 303 if ((Socket->SharedData->ServiceFlags1 & XP1_SUPPORT_MULTIPOINT) == 0) 304 { 305 /* The Provider doesn't actually support Multipoint */ 306 Status = WSAEINVAL; 307 goto error; 308 } 309 AfdPacket->EndpointFlags |= AFD_ENDPOINT_MULTIPOINT; 310 311 if (dwFlags & WSA_FLAG_MULTIPOINT_C_ROOT) 312 { 313 if (((Socket->SharedData->ServiceFlags1 & XP1_MULTIPOINT_CONTROL_PLANE) == 0) 314 || ((dwFlags & WSA_FLAG_MULTIPOINT_C_LEAF) != 0)) 315 { 316 /* The Provider doesn't support Control Planes, or you already gave a leaf */ 317 Status = WSAEINVAL; 318 goto error; 319 } 320 AfdPacket->EndpointFlags |= AFD_ENDPOINT_C_ROOT; 321 } 322 323 if (dwFlags & WSA_FLAG_MULTIPOINT_D_ROOT) 324 { 325 if (((Socket->SharedData->ServiceFlags1 & XP1_MULTIPOINT_DATA_PLANE) == 0) 326 || ((dwFlags & WSA_FLAG_MULTIPOINT_D_LEAF) != 0)) 327 { 328 /* The Provider doesn't support Data Planes, or you already gave a leaf */ 329 Status = WSAEINVAL; 330 goto error; 331 } 332 AfdPacket->EndpointFlags |= AFD_ENDPOINT_D_ROOT; 333 } 334 } 335 336 /* Set up Object Attributes */ 337 InitializeObjectAttributes (&Object, 338 &DevName, 339 OBJ_CASE_INSENSITIVE | OBJ_INHERIT, 340 0, 341 0); 342 343 /* Create the Socket as asynchronous. That means we have to block 344 ourselves after every call to NtDeviceIoControlFile. This is 345 because the kernel doesn't support overlapping synchronous I/O 346 requests (made from multiple threads) at this time (Sep 2005) */ 347 Status = NtCreateFile(&Sock, 348 GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 349 &Object, 350 &IOSB, 351 NULL, 352 0, 353 FILE_SHARE_READ | FILE_SHARE_WRITE, 354 FILE_OPEN_IF, 355 0, 356 EABuffer, 357 SizeOfEA); 358 359 HeapFree(GlobalHeap, 0, EABuffer); 360 361 if (!NT_SUCCESS(Status)) 362 { 363 ERR("Failed to open socket. Status 0x%08x\n", Status); 364 Status = TranslateNtStatusError(Status); 365 goto error; 366 } 367 368 /* Save Handle */ 369 Socket->Handle = (SOCKET)Sock; 370 371 /* Save Group Info */ 372 if (g != 0) 373 { 374 GetSocketInformation(Socket, 375 AFD_INFO_GROUP_ID_TYPE, 376 NULL, 377 NULL, 378 &GroupData, 379 NULL, 380 NULL); 381 Socket->SharedData->GroupID = GroupData.u.LowPart; 382 Socket->SharedData->GroupType = GroupData.u.HighPart; 383 } 384 385 /* Get Window Sizes and Save them */ 386 GetSocketInformation (Socket, 387 AFD_INFO_SEND_WINDOW_SIZE, 388 NULL, 389 &Socket->SharedData->SizeOfSendBuffer, 390 NULL, 391 NULL, 392 NULL); 393 394 GetSocketInformation (Socket, 395 AFD_INFO_RECEIVE_WINDOW_SIZE, 396 NULL, 397 &Socket->SharedData->SizeOfRecvBuffer, 398 NULL, 399 NULL, 400 NULL); 401 ok: 402 403 /* Save in Process Sockets List */ 404 EnterCriticalSection(&SocketListLock); 405 Socket->NextSocket = SocketListHead; 406 SocketListHead = Socket; 407 LeaveCriticalSection(&SocketListLock); 408 409 /* Create the Socket Context */ 410 CreateContext(Socket); 411 412 /* Notify Winsock */ 413 Upcalls.lpWPUModifyIFSHandle(Socket->ProtocolInfo.dwCatalogEntryId, (SOCKET)Sock, lpErrno); 414 415 /* Return Socket Handle */ 416 TRACE("Success %x\n", Sock); 417 418 return (SOCKET)Sock; 419 420 error: 421 ERR("Ending %x\n", Status); 422 423 if( SharedData ) 424 { 425 UnmapViewOfFile(SharedData); 426 NtClose(UlongToHandle(lpProtocolInfo->dwServiceFlags3)); 427 } 428 else 429 { 430 if( Socket && Socket->SharedData ) 431 HeapFree(GlobalHeap, 0, Socket->SharedData); 432 } 433 434 if( Socket ) 435 HeapFree(GlobalHeap, 0, Socket); 436 437 if( EABuffer ) 438 HeapFree(GlobalHeap, 0, EABuffer); 439 440 if( lpErrno ) 441 *lpErrno = Status; 442 443 return INVALID_SOCKET; 444 } 445 446 447 INT 448 WSPAPI 449 WSPDuplicateSocket( 450 IN SOCKET Handle, 451 IN DWORD dwProcessId, 452 OUT LPWSAPROTOCOL_INFOW lpProtocolInfo, 453 OUT LPINT lpErrno) 454 { 455 HANDLE hProcess, hDuplicatedSharedData, hDuplicatedHandle; 456 PSOCKET_INFORMATION Socket; 457 PSOCK_SHARED_INFO pSharedData, pOldSharedData; 458 BOOL bDuplicated; 459 460 if (Handle == INVALID_SOCKET) 461 return MsafdReturnWithErrno(STATUS_INVALID_PARAMETER, lpErrno, 0, NULL); 462 Socket = GetSocketStructure(Handle); 463 if( !Socket ) 464 { 465 if( lpErrno ) 466 *lpErrno = WSAENOTSOCK; 467 return SOCKET_ERROR; 468 } 469 if ( !(hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId)) ) 470 return MsafdReturnWithErrno(STATUS_INVALID_PARAMETER, lpErrno, 0, NULL); 471 472 /* It is a not yet duplicated socket, so map the memory, copy the SharedData and free heap */ 473 if( Socket->SharedDataHandle == INVALID_HANDLE_VALUE ) 474 { 475 Socket->SharedDataHandle = CreateFileMapping(INVALID_HANDLE_VALUE, 476 NULL, 477 PAGE_READWRITE | SEC_COMMIT, 478 0, 479 (sizeof(SOCK_SHARED_INFO) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1), 480 NULL); 481 if( Socket->SharedDataHandle == INVALID_HANDLE_VALUE ) 482 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL); 483 pSharedData = MapViewOfFile(Socket->SharedDataHandle, 484 FILE_MAP_ALL_ACCESS, 485 0, 486 0, 487 sizeof(SOCK_SHARED_INFO)); 488 489 RtlCopyMemory(pSharedData, Socket->SharedData, sizeof(SOCK_SHARED_INFO)); 490 pOldSharedData = Socket->SharedData; 491 Socket->SharedData = pSharedData; 492 HeapFree(GlobalHeap, 0, pOldSharedData); 493 } 494 /* Duplicate the handles for the new process */ 495 bDuplicated = DuplicateHandle(GetCurrentProcess(), 496 Socket->SharedDataHandle, 497 hProcess, 498 (LPHANDLE)&hDuplicatedSharedData, 499 0, 500 FALSE, 501 DUPLICATE_SAME_ACCESS); 502 if (!bDuplicated) 503 { 504 NtClose(hProcess); 505 return MsafdReturnWithErrno(STATUS_ACCESS_DENIED, lpErrno, 0, NULL); 506 } 507 bDuplicated = DuplicateHandle(GetCurrentProcess(), 508 (HANDLE)Socket->Handle, 509 hProcess, 510 (LPHANDLE)&hDuplicatedHandle, 511 0, 512 FALSE, 513 DUPLICATE_SAME_ACCESS); 514 NtClose(hProcess); 515 if( !bDuplicated ) 516 return MsafdReturnWithErrno(STATUS_ACCESS_DENIED, lpErrno, 0, NULL); 517 518 519 if (!lpProtocolInfo) 520 return MsafdReturnWithErrno(STATUS_ACCESS_VIOLATION, lpErrno, 0, NULL); 521 522 RtlCopyMemory(lpProtocolInfo, &Socket->ProtocolInfo, sizeof(*lpProtocolInfo)); 523 524 lpProtocolInfo->iAddressFamily = Socket->SharedData->AddressFamily; 525 lpProtocolInfo->iProtocol = Socket->SharedData->Protocol; 526 lpProtocolInfo->iSocketType = Socket->SharedData->SocketType; 527 lpProtocolInfo->dwServiceFlags3 = HandleToUlong(hDuplicatedSharedData); 528 lpProtocolInfo->dwServiceFlags4 = HandleToUlong(hDuplicatedHandle); 529 530 if( lpErrno ) 531 *lpErrno = NO_ERROR; 532 533 return NO_ERROR; 534 } 535 536 INT 537 TranslateNtStatusError(NTSTATUS Status) 538 { 539 switch (Status) 540 { 541 case STATUS_CANT_WAIT: 542 return WSAEWOULDBLOCK; 543 544 case STATUS_TIMEOUT: 545 return WSAETIMEDOUT; 546 547 case STATUS_SUCCESS: 548 return NO_ERROR; 549 550 case STATUS_FILE_CLOSED: 551 return WSAECONNRESET; 552 553 case STATUS_END_OF_FILE: 554 return WSAESHUTDOWN; 555 556 case STATUS_PENDING: 557 return WSA_IO_PENDING; 558 559 case STATUS_BUFFER_TOO_SMALL: 560 case STATUS_BUFFER_OVERFLOW: 561 return WSAEMSGSIZE; 562 563 case STATUS_NO_MEMORY: 564 case STATUS_INSUFFICIENT_RESOURCES: 565 return WSAENOBUFS; 566 567 case STATUS_INVALID_CONNECTION: 568 return WSAENOTCONN; 569 570 case STATUS_PROTOCOL_NOT_SUPPORTED: 571 return WSAEAFNOSUPPORT; 572 573 case STATUS_INVALID_ADDRESS: 574 return WSAEADDRNOTAVAIL; 575 576 case STATUS_REMOTE_NOT_LISTENING: 577 case STATUS_REMOTE_DISCONNECT: 578 return WSAECONNREFUSED; 579 580 case STATUS_NETWORK_UNREACHABLE: 581 return WSAENETUNREACH; 582 583 case STATUS_HOST_UNREACHABLE: 584 return WSAEHOSTUNREACH; 585 586 case STATUS_INVALID_PARAMETER: 587 return WSAEINVAL; 588 589 case STATUS_CANCELLED: 590 return WSA_OPERATION_ABORTED; 591 592 case STATUS_ADDRESS_ALREADY_EXISTS: 593 return WSAEADDRINUSE; 594 595 case STATUS_LOCAL_DISCONNECT: 596 return WSAECONNABORTED; 597 598 case STATUS_ACCESS_VIOLATION: 599 return WSAEFAULT; 600 601 case STATUS_ACCESS_DENIED: 602 return WSAEACCES; 603 604 case STATUS_NOT_IMPLEMENTED: 605 return WSAEOPNOTSUPP; 606 607 default: 608 ERR("MSAFD: Unhandled NTSTATUS value: 0x%x\n", Status); 609 return WSAENETDOWN; 610 } 611 } 612 613 /* 614 * FUNCTION: Closes an open socket 615 * ARGUMENTS: 616 * s = Socket descriptor 617 * lpErrno = Address of buffer for error information 618 * RETURNS: 619 * NO_ERROR, or SOCKET_ERROR if the socket could not be closed 620 */ 621 INT 622 WSPAPI 623 WSPCloseSocket(IN SOCKET Handle, 624 OUT LPINT lpErrno) 625 { 626 IO_STATUS_BLOCK IoStatusBlock; 627 PSOCKET_INFORMATION Socket = NULL, CurrentSocket; 628 NTSTATUS Status; 629 HANDLE SockEvent; 630 AFD_DISCONNECT_INFO DisconnectInfo; 631 SOCKET_STATE OldState; 632 LONG LingerWait = -1; 633 DWORD References; 634 635 /* Get the Socket Structure associate to this Socket*/ 636 Socket = GetSocketStructure(Handle); 637 if (!Socket) 638 { 639 if (lpErrno) *lpErrno = WSAENOTSOCK; 640 return SOCKET_ERROR; 641 } 642 643 /* Create the Wait Event */ 644 Status = NtCreateEvent(&SockEvent, 645 EVENT_ALL_ACCESS, 646 NULL, 647 SynchronizationEvent, 648 FALSE); 649 650 if(!NT_SUCCESS(Status)) 651 { 652 ERR("NtCreateEvent failed: 0x%08x", Status); 653 return SOCKET_ERROR; 654 } 655 656 if (Socket->HelperEvents & WSH_NOTIFY_CLOSE) 657 { 658 Status = Socket->HelperData->WSHNotify(Socket->HelperContext, 659 Socket->Handle, 660 Socket->TdiAddressHandle, 661 Socket->TdiConnectionHandle, 662 WSH_NOTIFY_CLOSE); 663 664 if (Status) 665 { 666 if (lpErrno) *lpErrno = Status; 667 ERR("WSHNotify failed. Error 0x%#x", Status); 668 NtClose(SockEvent); 669 return SOCKET_ERROR; 670 } 671 } 672 673 /* If a Close is already in Process, give up */ 674 if (Socket->SharedData->State == SocketClosed) 675 { 676 WARN("Socket is closing.\n"); 677 NtClose(SockEvent); 678 if (lpErrno) *lpErrno = WSAENOTSOCK; 679 return SOCKET_ERROR; 680 } 681 682 /* Decrement reference count on SharedData */ 683 References = InterlockedDecrement(&Socket->SharedData->RefCount); 684 if (References) 685 goto ok; 686 687 /* Set the state to close */ 688 OldState = Socket->SharedData->State; 689 Socket->SharedData->State = SocketClosed; 690 691 /* If SO_LINGER is ON and the Socket is connected, we need to disconnect */ 692 /* FIXME: Should we do this on Datagram Sockets too? */ 693 if ((OldState == SocketConnected) && (Socket->SharedData->LingerData.l_onoff)) 694 { 695 ULONG SendsInProgress; 696 ULONG SleepWait; 697 698 /* We need to respect the timeout */ 699 SleepWait = 100; 700 LingerWait = Socket->SharedData->LingerData.l_linger * 1000; 701 702 /* Loop until no more sends are pending, within the timeout */ 703 while (LingerWait) 704 { 705 /* Find out how many Sends are in Progress */ 706 if (GetSocketInformation(Socket, 707 AFD_INFO_SENDS_IN_PROGRESS, 708 NULL, 709 &SendsInProgress, 710 NULL, 711 NULL, 712 NULL)) 713 { 714 /* Bail out if anything but NO_ERROR */ 715 LingerWait = 0; 716 break; 717 } 718 719 /* Bail out if no more sends are pending */ 720 if (!SendsInProgress) 721 { 722 LingerWait = -1; 723 break; 724 } 725 726 /* 727 * We have to execute a sleep, so it's kind of like 728 * a block. If the socket is Nonblock, we cannot 729 * go on since asynchronous operation is expected 730 * and we cannot offer it 731 */ 732 if (Socket->SharedData->NonBlocking) 733 { 734 WARN("Would block!\n"); 735 NtClose(SockEvent); 736 Socket->SharedData->State = OldState; 737 if (lpErrno) *lpErrno = WSAEWOULDBLOCK; 738 return SOCKET_ERROR; 739 } 740 741 /* Now we can sleep, and decrement the linger wait */ 742 /* 743 * FIXME: It seems Windows does some funky acceleration 744 * since the waiting seems to be longer and longer. I 745 * don't think this improves performance so much, so we 746 * wait a fixed time instead. 747 */ 748 Sleep(SleepWait); 749 LingerWait -= SleepWait; 750 } 751 } 752 753 if (OldState == SocketConnected) 754 { 755 if (LingerWait <= 0) 756 { 757 DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(0); 758 DisconnectInfo.DisconnectType = LingerWait < 0 ? AFD_DISCONNECT_SEND : AFD_DISCONNECT_ABORT; 759 760 if (((DisconnectInfo.DisconnectType & AFD_DISCONNECT_SEND) && (!Socket->SharedData->SendShutdown)) || 761 ((DisconnectInfo.DisconnectType & AFD_DISCONNECT_ABORT) && (!Socket->SharedData->ReceiveShutdown))) 762 { 763 /* Send IOCTL */ 764 Status = NtDeviceIoControlFile((HANDLE)Handle, 765 SockEvent, 766 NULL, 767 NULL, 768 &IoStatusBlock, 769 IOCTL_AFD_DISCONNECT, 770 &DisconnectInfo, 771 sizeof(DisconnectInfo), 772 NULL, 773 0); 774 775 /* Wait for return */ 776 if (Status == STATUS_PENDING) 777 { 778 WaitForSingleObject(SockEvent, INFINITE); 779 Status = IoStatusBlock.Status; 780 } 781 } 782 } 783 } 784 785 /* Cleanup Time! */ 786 Socket->HelperContext = NULL; 787 Socket->SharedData->AsyncDisabledEvents = -1; 788 NtClose(Socket->TdiAddressHandle); 789 Socket->TdiAddressHandle = NULL; 790 NtClose(Socket->TdiConnectionHandle); 791 Socket->TdiConnectionHandle = NULL; 792 ok: 793 EnterCriticalSection(&SocketListLock); 794 if (SocketListHead == Socket) 795 { 796 SocketListHead = SocketListHead->NextSocket; 797 } 798 else 799 { 800 CurrentSocket = SocketListHead; 801 while (CurrentSocket->NextSocket) 802 { 803 if (CurrentSocket->NextSocket == Socket) 804 { 805 CurrentSocket->NextSocket = CurrentSocket->NextSocket->NextSocket; 806 break; 807 } 808 809 CurrentSocket = CurrentSocket->NextSocket; 810 } 811 } 812 LeaveCriticalSection(&SocketListLock); 813 814 /* Close the handle */ 815 NtClose((HANDLE)Handle); 816 NtClose(SockEvent); 817 818 if( Socket->SharedDataHandle != INVALID_HANDLE_VALUE ) 819 { 820 /* It is a duplicated socket, so unmap the memory */ 821 UnmapViewOfFile(Socket->SharedData); 822 NtClose(Socket->SharedDataHandle); 823 Socket->SharedData = NULL; 824 } 825 if( !References && Socket->SharedData ) 826 { 827 HeapFree(GlobalHeap, 0, Socket->SharedData); 828 } 829 HeapFree(GlobalHeap, 0, Socket); 830 return MsafdReturnWithErrno(Status, lpErrno, 0, NULL); 831 } 832 833 834 /* 835 * FUNCTION: Associates a local address with a socket 836 * ARGUMENTS: 837 * s = Socket descriptor 838 * name = Pointer to local address 839 * namelen = Length of name 840 * lpErrno = Address of buffer for error information 841 * RETURNS: 842 * 0, or SOCKET_ERROR if the socket could not be bound 843 */ 844 INT 845 WSPAPI 846 WSPBind(SOCKET Handle, 847 const struct sockaddr *SocketAddress, 848 int SocketAddressLength, 849 LPINT lpErrno) 850 { 851 IO_STATUS_BLOCK IOSB; 852 PAFD_BIND_DATA BindData; 853 PSOCKET_INFORMATION Socket = NULL; 854 NTSTATUS Status; 855 SOCKADDR_INFO SocketInfo; 856 HANDLE SockEvent; 857 858 /* Get the Socket Structure associate to this Socket*/ 859 Socket = GetSocketStructure(Handle); 860 if (!Socket) 861 { 862 if (lpErrno) *lpErrno = WSAENOTSOCK; 863 return SOCKET_ERROR; 864 } 865 if (Socket->SharedData->State != SocketOpen) 866 { 867 if (lpErrno) *lpErrno = WSAEINVAL; 868 return SOCKET_ERROR; 869 } 870 if (!SocketAddress || SocketAddressLength < Socket->SharedData->SizeOfLocalAddress) 871 { 872 if (lpErrno) *lpErrno = WSAEINVAL; 873 return SOCKET_ERROR; 874 } 875 876 /* Get Address Information */ 877 Socket->HelperData->WSHGetSockaddrType ((PSOCKADDR)SocketAddress, 878 SocketAddressLength, 879 &SocketInfo); 880 881 if (SocketInfo.AddressInfo == SockaddrAddressInfoBroadcast && !Socket->SharedData->Broadcast) 882 { 883 if (lpErrno) *lpErrno = WSAEADDRNOTAVAIL; 884 return SOCKET_ERROR; 885 } 886 887 Status = NtCreateEvent(&SockEvent, 888 EVENT_ALL_ACCESS, 889 NULL, 890 SynchronizationEvent, 891 FALSE); 892 893 if (!NT_SUCCESS(Status)) 894 { 895 return SOCKET_ERROR; 896 } 897 898 /* See below */ 899 BindData = HeapAlloc(GlobalHeap, 0, 0xA + SocketAddressLength); 900 if (!BindData) 901 { 902 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL); 903 } 904 905 /* Set up Address in TDI Format */ 906 BindData->Address.TAAddressCount = 1; 907 BindData->Address.Address[0].AddressLength = (USHORT)(SocketAddressLength - sizeof(SocketAddress->sa_family)); 908 BindData->Address.Address[0].AddressType = SocketAddress->sa_family; 909 RtlCopyMemory (BindData->Address.Address[0].Address, 910 SocketAddress->sa_data, 911 SocketAddressLength - sizeof(SocketAddress->sa_family)); 912 913 /* Set the Share Type */ 914 if (Socket->SharedData->ExclusiveAddressUse) 915 { 916 BindData->ShareType = AFD_SHARE_EXCLUSIVE; 917 } 918 else if (SocketInfo.EndpointInfo == SockaddrEndpointInfoWildcard) 919 { 920 BindData->ShareType = AFD_SHARE_WILDCARD; 921 } 922 else if (Socket->SharedData->ReuseAddresses) 923 { 924 BindData->ShareType = AFD_SHARE_REUSE; 925 } 926 else 927 { 928 BindData->ShareType = AFD_SHARE_UNIQUE; 929 } 930 931 /* Send IOCTL */ 932 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle, 933 SockEvent, 934 NULL, 935 NULL, 936 &IOSB, 937 IOCTL_AFD_BIND, 938 BindData, 939 0xA + Socket->SharedData->SizeOfLocalAddress, /* Can't figure out a way to calculate this in C*/ 940 BindData, 941 0xA + Socket->SharedData->SizeOfLocalAddress); /* Can't figure out a way to calculate this C */ 942 943 /* Wait for return */ 944 if (Status == STATUS_PENDING) 945 { 946 WaitForSingleObject(SockEvent, INFINITE); 947 Status = IOSB.Status; 948 } 949 950 NtClose( SockEvent ); 951 HeapFree(GlobalHeap, 0, BindData); 952 953 Socket->SharedData->SocketLastError = TranslateNtStatusError(Status); 954 if (Status != STATUS_SUCCESS) 955 return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL ); 956 957 /* Set up Socket Data */ 958 Socket->SharedData->State = SocketBound; 959 Socket->TdiAddressHandle = (HANDLE)IOSB.Information; 960 961 if (Socket->HelperEvents & WSH_NOTIFY_BIND) 962 { 963 Status = Socket->HelperData->WSHNotify(Socket->HelperContext, 964 Socket->Handle, 965 Socket->TdiAddressHandle, 966 Socket->TdiConnectionHandle, 967 WSH_NOTIFY_BIND); 968 969 if (Status) 970 { 971 if (lpErrno) *lpErrno = Status; 972 return SOCKET_ERROR; 973 } 974 } 975 976 return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL ); 977 } 978 979 int 980 WSPAPI 981 WSPListen(SOCKET Handle, 982 int Backlog, 983 LPINT lpErrno) 984 { 985 IO_STATUS_BLOCK IOSB; 986 AFD_LISTEN_DATA ListenData; 987 PSOCKET_INFORMATION Socket = NULL; 988 HANDLE SockEvent; 989 NTSTATUS Status; 990 991 /* Get the Socket Structure associate to this Socket*/ 992 Socket = GetSocketStructure(Handle); 993 if (!Socket) 994 { 995 if (lpErrno) *lpErrno = WSAENOTSOCK; 996 return SOCKET_ERROR; 997 } 998 999 if (Socket->SharedData->Listening) 1000 return NO_ERROR; 1001 1002 Status = NtCreateEvent(&SockEvent, 1003 EVENT_ALL_ACCESS, 1004 NULL, 1005 SynchronizationEvent, 1006 FALSE); 1007 1008 if( !NT_SUCCESS(Status) ) 1009 return SOCKET_ERROR; 1010 1011 /* Set Up Listen Structure */ 1012 ListenData.UseSAN = FALSE; 1013 ListenData.UseDelayedAcceptance = Socket->SharedData->UseDelayedAcceptance; 1014 ListenData.Backlog = Backlog; 1015 1016 /* Send IOCTL */ 1017 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle, 1018 SockEvent, 1019 NULL, 1020 NULL, 1021 &IOSB, 1022 IOCTL_AFD_START_LISTEN, 1023 &ListenData, 1024 sizeof(ListenData), 1025 NULL, 1026 0); 1027 1028 /* Wait for return */ 1029 if (Status == STATUS_PENDING) 1030 { 1031 WaitForSingleObject(SockEvent, INFINITE); 1032 Status = IOSB.Status; 1033 } 1034 1035 NtClose( SockEvent ); 1036 1037 Socket->SharedData->SocketLastError = TranslateNtStatusError(Status); 1038 if (Status != STATUS_SUCCESS) 1039 return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL ); 1040 1041 /* Set to Listening */ 1042 Socket->SharedData->Listening = TRUE; 1043 1044 if (Socket->HelperEvents & WSH_NOTIFY_LISTEN) 1045 { 1046 Status = Socket->HelperData->WSHNotify(Socket->HelperContext, 1047 Socket->Handle, 1048 Socket->TdiAddressHandle, 1049 Socket->TdiConnectionHandle, 1050 WSH_NOTIFY_LISTEN); 1051 1052 if (Status) 1053 { 1054 if (lpErrno) *lpErrno = Status; 1055 return SOCKET_ERROR; 1056 } 1057 } 1058 1059 return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL ); 1060 } 1061 1062 1063 int 1064 WSPAPI 1065 WSPSelect(IN int nfds, 1066 IN OUT fd_set *readfds OPTIONAL, 1067 IN OUT fd_set *writefds OPTIONAL, 1068 IN OUT fd_set *exceptfds OPTIONAL, 1069 IN const struct timeval *timeout OPTIONAL, 1070 OUT LPINT lpErrno) 1071 { 1072 IO_STATUS_BLOCK IOSB; 1073 PAFD_POLL_INFO PollInfo; 1074 NTSTATUS Status; 1075 ULONG HandleCount; 1076 ULONG PollBufferSize; 1077 PVOID PollBuffer; 1078 ULONG i, j = 0, x; 1079 HANDLE SockEvent; 1080 LARGE_INTEGER Timeout; 1081 PSOCKET_INFORMATION Socket; 1082 SOCKET Handle; 1083 ULONG Events; 1084 fd_set selectfds; 1085 1086 /* Find out how many sockets we have, and how large the buffer needs 1087 * to be */ 1088 FD_ZERO(&selectfds); 1089 if (readfds != NULL) 1090 { 1091 for (i = 0; i < readfds->fd_count; i++) 1092 { 1093 FD_SET(readfds->fd_array[i], &selectfds); 1094 } 1095 } 1096 if (writefds != NULL) 1097 { 1098 for (i = 0; i < writefds->fd_count; i++) 1099 { 1100 FD_SET(writefds->fd_array[i], &selectfds); 1101 } 1102 } 1103 if (exceptfds != NULL) 1104 { 1105 for (i = 0; i < exceptfds->fd_count; i++) 1106 { 1107 FD_SET(exceptfds->fd_array[i], &selectfds); 1108 } 1109 } 1110 1111 HandleCount = selectfds.fd_count; 1112 1113 if ( HandleCount == 0 ) 1114 { 1115 WARN("No handles! Returning SOCKET_ERROR\n", HandleCount); 1116 if (lpErrno) *lpErrno = WSAEINVAL; 1117 return SOCKET_ERROR; 1118 } 1119 1120 PollBufferSize = sizeof(*PollInfo) + ((HandleCount - 1) * sizeof(AFD_HANDLE)); 1121 1122 TRACE("HandleCount: %u BufferSize: %u\n", HandleCount, PollBufferSize); 1123 1124 /* Convert Timeout to NT Format */ 1125 if (timeout == NULL) 1126 { 1127 Timeout.u.LowPart = -1; 1128 Timeout.u.HighPart = 0x7FFFFFFF; 1129 TRACE("Infinite timeout\n"); 1130 } 1131 else 1132 { 1133 Timeout = RtlEnlargedIntegerMultiply 1134 ((timeout->tv_sec * 1000) + (timeout->tv_usec / 1000), -10000); 1135 /* Negative timeouts are illegal. Since the kernel represents an 1136 * incremental timeout as a negative number, we check for a positive 1137 * result. 1138 */ 1139 if (Timeout.QuadPart > 0) 1140 { 1141 if (lpErrno) *lpErrno = WSAEINVAL; 1142 return SOCKET_ERROR; 1143 } 1144 TRACE("Timeout: Orig %d.%06d kernel %d\n", 1145 timeout->tv_sec, timeout->tv_usec, 1146 Timeout.u.LowPart); 1147 } 1148 1149 Status = NtCreateEvent(&SockEvent, 1150 EVENT_ALL_ACCESS, 1151 NULL, 1152 SynchronizationEvent, 1153 FALSE); 1154 1155 if(!NT_SUCCESS(Status)) 1156 { 1157 if (lpErrno) 1158 *lpErrno = WSAEFAULT; 1159 1160 ERR("NtCreateEvent failed, 0x%08x\n", Status); 1161 return SOCKET_ERROR; 1162 } 1163 1164 /* Allocate */ 1165 PollBuffer = HeapAlloc(GlobalHeap, 0, PollBufferSize); 1166 1167 if (!PollBuffer) 1168 { 1169 if (lpErrno) 1170 *lpErrno = WSAEFAULT; 1171 NtClose(SockEvent); 1172 return SOCKET_ERROR; 1173 } 1174 1175 PollInfo = (PAFD_POLL_INFO)PollBuffer; 1176 1177 RtlZeroMemory( PollInfo, PollBufferSize ); 1178 1179 /* Number of handles for AFD to Check */ 1180 PollInfo->Exclusive = FALSE; 1181 PollInfo->Timeout = Timeout; 1182 1183 for (i = 0; i < selectfds.fd_count; i++) 1184 { 1185 PollInfo->Handles[i].Handle = selectfds.fd_array[i]; 1186 } 1187 if (readfds != NULL) { 1188 for (i = 0; i < readfds->fd_count; i++) 1189 { 1190 for (j = 0; j < HandleCount; j++) 1191 { 1192 if (PollInfo->Handles[j].Handle == readfds->fd_array[i]) 1193 break; 1194 } 1195 if (j >= HandleCount) 1196 { 1197 ERR("Error while counting readfds %ld > %ld\n", j, HandleCount); 1198 if (lpErrno) *lpErrno = WSAEFAULT; 1199 HeapFree(GlobalHeap, 0, PollBuffer); 1200 NtClose(SockEvent); 1201 return SOCKET_ERROR; 1202 } 1203 Socket = GetSocketStructure(readfds->fd_array[i]); 1204 if (!Socket) 1205 { 1206 ERR("Invalid socket handle provided in readfds %d\n", readfds->fd_array[i]); 1207 if (lpErrno) *lpErrno = WSAENOTSOCK; 1208 HeapFree(GlobalHeap, 0, PollBuffer); 1209 NtClose(SockEvent); 1210 return SOCKET_ERROR; 1211 } 1212 PollInfo->Handles[j].Events |= AFD_EVENT_RECEIVE | 1213 AFD_EVENT_DISCONNECT | 1214 AFD_EVENT_ABORT | 1215 AFD_EVENT_CLOSE | 1216 AFD_EVENT_ACCEPT; 1217 //if (Socket->SharedData->OobInline != 0) 1218 // PollInfo->Handles[j].Events |= AFD_EVENT_OOB_RECEIVE; 1219 } 1220 } 1221 if (writefds != NULL) 1222 { 1223 for (i = 0; i < writefds->fd_count; i++) 1224 { 1225 for (j = 0; j < HandleCount; j++) 1226 { 1227 if (PollInfo->Handles[j].Handle == writefds->fd_array[i]) 1228 break; 1229 } 1230 if (j >= HandleCount) 1231 { 1232 ERR("Error while counting writefds %ld > %ld\n", j, HandleCount); 1233 if (lpErrno) *lpErrno = WSAEFAULT; 1234 HeapFree(GlobalHeap, 0, PollBuffer); 1235 NtClose(SockEvent); 1236 return SOCKET_ERROR; 1237 } 1238 Socket = GetSocketStructure(writefds->fd_array[i]); 1239 if (!Socket) 1240 { 1241 ERR("Invalid socket handle provided in writefds %d\n", writefds->fd_array[i]); 1242 if (lpErrno) *lpErrno = WSAENOTSOCK; 1243 HeapFree(GlobalHeap, 0, PollBuffer); 1244 NtClose(SockEvent); 1245 return SOCKET_ERROR; 1246 } 1247 PollInfo->Handles[j].Handle = writefds->fd_array[i]; 1248 PollInfo->Handles[j].Events |= AFD_EVENT_SEND; 1249 if (Socket->SharedData->NonBlocking != 0) 1250 PollInfo->Handles[j].Events |= AFD_EVENT_CONNECT; 1251 } 1252 } 1253 if (exceptfds != NULL) 1254 { 1255 for (i = 0; i < exceptfds->fd_count; i++) 1256 { 1257 for (j = 0; j < HandleCount; j++) 1258 { 1259 if (PollInfo->Handles[j].Handle == exceptfds->fd_array[i]) 1260 break; 1261 } 1262 if (j > HandleCount) 1263 { 1264 ERR("Error while counting exceptfds %ld > %ld\n", j, HandleCount); 1265 if (lpErrno) *lpErrno = WSAEFAULT; 1266 HeapFree(GlobalHeap, 0, PollBuffer); 1267 NtClose(SockEvent); 1268 return SOCKET_ERROR; 1269 } 1270 Socket = GetSocketStructure(exceptfds->fd_array[i]); 1271 if (!Socket) 1272 { 1273 TRACE("Invalid socket handle provided in exceptfds %d\n", exceptfds->fd_array[i]); 1274 if (lpErrno) *lpErrno = WSAENOTSOCK; 1275 HeapFree(GlobalHeap, 0, PollBuffer); 1276 NtClose(SockEvent); 1277 return SOCKET_ERROR; 1278 } 1279 PollInfo->Handles[j].Handle = exceptfds->fd_array[i]; 1280 if (Socket->SharedData->OobInline == 0) 1281 PollInfo->Handles[j].Events |= AFD_EVENT_OOB_RECEIVE; 1282 if (Socket->SharedData->NonBlocking != 0) 1283 PollInfo->Handles[j].Events |= AFD_EVENT_CONNECT_FAIL; 1284 } 1285 } 1286 1287 PollInfo->HandleCount = HandleCount; 1288 PollBufferSize = FIELD_OFFSET(AFD_POLL_INFO, Handles) + PollInfo->HandleCount * sizeof(AFD_HANDLE); 1289 1290 /* Send IOCTL */ 1291 Status = NtDeviceIoControlFile((HANDLE)PollInfo->Handles[0].Handle, 1292 SockEvent, 1293 NULL, 1294 NULL, 1295 &IOSB, 1296 IOCTL_AFD_SELECT, 1297 PollInfo, 1298 PollBufferSize, 1299 PollInfo, 1300 PollBufferSize); 1301 1302 TRACE("DeviceIoControlFile => %x\n", Status); 1303 1304 /* Wait for Completion */ 1305 if (Status == STATUS_PENDING) 1306 { 1307 WaitForSingleObject(SockEvent, INFINITE); 1308 Status = IOSB.Status; 1309 } 1310 1311 /* Clear the Structures */ 1312 if( readfds ) 1313 FD_ZERO(readfds); 1314 if( writefds ) 1315 FD_ZERO(writefds); 1316 if( exceptfds ) 1317 FD_ZERO(exceptfds); 1318 1319 /* Loop through return structure */ 1320 HandleCount = PollInfo->HandleCount; 1321 1322 /* Return in FDSET Format */ 1323 for (i = 0; i < HandleCount; i++) 1324 { 1325 Events = PollInfo->Handles[i].Events; 1326 Handle = PollInfo->Handles[i].Handle; 1327 for(x = 1; x; x<<=1) 1328 { 1329 Socket = GetSocketStructure(Handle); 1330 if (!Socket) 1331 { 1332 TRACE("Invalid socket handle found %d\n", Handle); 1333 if (lpErrno) *lpErrno = WSAENOTSOCK; 1334 HeapFree(GlobalHeap, 0, PollBuffer); 1335 NtClose(SockEvent); 1336 return SOCKET_ERROR; 1337 } 1338 switch (Events & x) 1339 { 1340 case AFD_EVENT_RECEIVE: 1341 case AFD_EVENT_DISCONNECT: 1342 case AFD_EVENT_ABORT: 1343 case AFD_EVENT_ACCEPT: 1344 case AFD_EVENT_CLOSE: 1345 TRACE("Event %x on handle %x\n", 1346 Events, 1347 Handle); 1348 if ((Events & x) == AFD_EVENT_DISCONNECT || (Events & x) == AFD_EVENT_CLOSE) 1349 Socket->SharedData->SocketLastError = WSAECONNRESET; 1350 if ((Events & x) == AFD_EVENT_ABORT) 1351 Socket->SharedData->SocketLastError = WSAECONNABORTED; 1352 if( readfds ) 1353 FD_SET(Handle, readfds); 1354 break; 1355 case AFD_EVENT_SEND: 1356 TRACE("Event %x on handle %x\n", 1357 Events, 1358 Handle); 1359 if (writefds) 1360 FD_SET(Handle, writefds); 1361 break; 1362 case AFD_EVENT_CONNECT: 1363 TRACE("Event %x on handle %x\n", 1364 Events, 1365 Handle); 1366 if( writefds && Socket->SharedData->NonBlocking != 0 ) 1367 FD_SET(Handle, writefds); 1368 break; 1369 case AFD_EVENT_OOB_RECEIVE: 1370 TRACE("Event %x on handle %x\n", 1371 Events, 1372 Handle); 1373 if( readfds && Socket->SharedData->OobInline != 0 ) 1374 FD_SET(Handle, readfds); 1375 if( exceptfds && Socket->SharedData->OobInline == 0 ) 1376 FD_SET(Handle, exceptfds); 1377 break; 1378 case AFD_EVENT_CONNECT_FAIL: 1379 TRACE("Event %x on handle %x\n", 1380 Events, 1381 Handle); 1382 if( exceptfds && Socket->SharedData->NonBlocking != 0 ) 1383 FD_SET(Handle, exceptfds); 1384 break; 1385 } 1386 } 1387 } 1388 1389 HeapFree( GlobalHeap, 0, PollBuffer ); 1390 NtClose( SockEvent ); 1391 1392 if( lpErrno ) 1393 { 1394 switch( IOSB.Status ) 1395 { 1396 case STATUS_SUCCESS: 1397 case STATUS_TIMEOUT: 1398 *lpErrno = 0; 1399 break; 1400 default: 1401 *lpErrno = WSAEINVAL; 1402 break; 1403 } 1404 TRACE("*lpErrno = %x\n", *lpErrno); 1405 } 1406 1407 HandleCount = (readfds ? readfds->fd_count : 0) + 1408 (writefds && writefds != readfds ? writefds->fd_count : 0) + 1409 (exceptfds && exceptfds != readfds && exceptfds != writefds ? exceptfds->fd_count : 0); 1410 1411 TRACE("%d events\n", HandleCount); 1412 1413 return HandleCount; 1414 } 1415 1416 DWORD 1417 GetCurrentTimeInSeconds(VOID) 1418 { 1419 SYSTEMTIME st1970 = { 1970, 1, 0, 1, 0, 0, 0, 0 }; 1420 union 1421 { 1422 FILETIME ft; 1423 ULONGLONG ll; 1424 } u1970, Time; 1425 1426 GetSystemTimeAsFileTime(&Time.ft); 1427 SystemTimeToFileTime(&st1970, &u1970.ft); 1428 return (DWORD)((Time.ll - u1970.ll) / 10000000ULL); 1429 } 1430 1431 _Must_inspect_result_ 1432 SOCKET 1433 WSPAPI 1434 WSPAccept( 1435 _In_ SOCKET Handle, 1436 _Out_writes_bytes_to_opt_(*addrlen, *addrlen) struct sockaddr FAR *SocketAddress, 1437 _Inout_opt_ LPINT SocketAddressLength, 1438 _In_opt_ LPCONDITIONPROC lpfnCondition, 1439 _In_opt_ DWORD_PTR dwCallbackData, 1440 _Out_ LPINT lpErrno) 1441 { 1442 IO_STATUS_BLOCK IOSB; 1443 PAFD_RECEIVED_ACCEPT_DATA ListenReceiveData; 1444 AFD_ACCEPT_DATA AcceptData; 1445 AFD_DEFER_ACCEPT_DATA DeferData; 1446 AFD_PENDING_ACCEPT_DATA PendingAcceptData; 1447 PSOCKET_INFORMATION Socket = NULL; 1448 NTSTATUS Status; 1449 struct fd_set ReadSet; 1450 struct timeval Timeout; 1451 PVOID PendingData = NULL; 1452 ULONG PendingDataLength = 0; 1453 PVOID CalleeDataBuffer; 1454 WSABUF CallerData, CalleeID, CallerID, CalleeData; 1455 PSOCKADDR RemoteAddress = NULL; 1456 GROUP GroupID = 0; 1457 ULONG CallBack; 1458 SOCKET AcceptSocket; 1459 PSOCKET_INFORMATION AcceptSocketInfo; 1460 UCHAR ReceiveBuffer[0x1A]; 1461 HANDLE SockEvent; 1462 1463 /* Get the Socket Structure associate to this Socket*/ 1464 Socket = GetSocketStructure(Handle); 1465 if (!Socket) 1466 { 1467 if (lpErrno) *lpErrno = WSAENOTSOCK; 1468 return SOCKET_ERROR; 1469 } 1470 if (!Socket->SharedData->Listening) 1471 { 1472 if (lpErrno) *lpErrno = WSAEINVAL; 1473 return SOCKET_ERROR; 1474 } 1475 if ((SocketAddress && !SocketAddressLength) || 1476 (SocketAddressLength && !SocketAddress) || 1477 (SocketAddressLength && *SocketAddressLength < sizeof(SOCKADDR))) 1478 { 1479 if (lpErrno) *lpErrno = WSAEFAULT; 1480 return INVALID_SOCKET; 1481 } 1482 1483 Status = NtCreateEvent(&SockEvent, 1484 EVENT_ALL_ACCESS, 1485 NULL, 1486 SynchronizationEvent, 1487 FALSE); 1488 1489 if( !NT_SUCCESS(Status) ) 1490 { 1491 return SOCKET_ERROR; 1492 } 1493 1494 /* Dynamic Structure...ugh */ 1495 ListenReceiveData = (PAFD_RECEIVED_ACCEPT_DATA)ReceiveBuffer; 1496 1497 /* If this is non-blocking, make sure there's something for us to accept */ 1498 FD_ZERO(&ReadSet); 1499 FD_SET(Socket->Handle, &ReadSet); 1500 Timeout.tv_sec=0; 1501 Timeout.tv_usec=0; 1502 1503 if (WSPSelect(0, &ReadSet, NULL, NULL, &Timeout, lpErrno) == SOCKET_ERROR) 1504 { 1505 NtClose(SockEvent); 1506 return SOCKET_ERROR; 1507 } 1508 1509 if (ReadSet.fd_array[0] != Socket->Handle) 1510 { 1511 NtClose(SockEvent); 1512 if (lpErrno) *lpErrno = WSAEWOULDBLOCK; 1513 return SOCKET_ERROR; 1514 } 1515 1516 /* Send IOCTL */ 1517 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle, 1518 SockEvent, 1519 NULL, 1520 NULL, 1521 &IOSB, 1522 IOCTL_AFD_WAIT_FOR_LISTEN, 1523 NULL, 1524 0, 1525 ListenReceiveData, 1526 0xA + sizeof(*ListenReceiveData)); 1527 1528 /* Wait for return */ 1529 if (Status == STATUS_PENDING) 1530 { 1531 WaitForSingleObject(SockEvent, INFINITE); 1532 Status = IOSB.Status; 1533 } 1534 1535 if (!NT_SUCCESS(Status)) 1536 { 1537 NtClose( SockEvent ); 1538 return MsafdReturnWithErrno( Status, lpErrno, 0, NULL ); 1539 } 1540 1541 if (lpfnCondition != NULL) 1542 { 1543 if ((Socket->SharedData->ServiceFlags1 & XP1_CONNECT_DATA) != 0) 1544 { 1545 /* Find out how much data is pending */ 1546 PendingAcceptData.SequenceNumber = ListenReceiveData->SequenceNumber; 1547 PendingAcceptData.ReturnSize = TRUE; 1548 1549 /* Send IOCTL */ 1550 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle, 1551 SockEvent, 1552 NULL, 1553 NULL, 1554 &IOSB, 1555 IOCTL_AFD_GET_PENDING_CONNECT_DATA, 1556 &PendingAcceptData, 1557 sizeof(PendingAcceptData), 1558 &PendingAcceptData, 1559 sizeof(PendingAcceptData)); 1560 1561 /* Wait for return */ 1562 if (Status == STATUS_PENDING) 1563 { 1564 WaitForSingleObject(SockEvent, INFINITE); 1565 Status = IOSB.Status; 1566 } 1567 1568 if (!NT_SUCCESS(Status)) 1569 { 1570 NtClose( SockEvent ); 1571 return MsafdReturnWithErrno( Status, lpErrno, 0, NULL ); 1572 } 1573 1574 /* How much data to allocate */ 1575 PendingDataLength = IOSB.Information; 1576 1577 if (PendingDataLength) 1578 { 1579 /* Allocate needed space */ 1580 PendingData = HeapAlloc(GlobalHeap, 0, PendingDataLength); 1581 if (!PendingData) 1582 { 1583 return MsafdReturnWithErrno( STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL ); 1584 } 1585 1586 /* We want the data now */ 1587 PendingAcceptData.ReturnSize = FALSE; 1588 1589 /* Send IOCTL */ 1590 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle, 1591 SockEvent, 1592 NULL, 1593 NULL, 1594 &IOSB, 1595 IOCTL_AFD_GET_PENDING_CONNECT_DATA, 1596 &PendingAcceptData, 1597 sizeof(PendingAcceptData), 1598 PendingData, 1599 PendingDataLength); 1600 1601 /* Wait for return */ 1602 if (Status == STATUS_PENDING) 1603 { 1604 WaitForSingleObject(SockEvent, INFINITE); 1605 Status = IOSB.Status; 1606 } 1607 1608 if (!NT_SUCCESS(Status)) 1609 { 1610 NtClose( SockEvent ); 1611 return MsafdReturnWithErrno( Status, lpErrno, 0, NULL ); 1612 } 1613 } 1614 } 1615 1616 if ((Socket->SharedData->ServiceFlags1 & XP1_QOS_SUPPORTED) != 0) 1617 { 1618 /* I don't support this yet */ 1619 } 1620 1621 /* Build Callee ID */ 1622 CalleeID.buf = (PVOID)Socket->LocalAddress; 1623 CalleeID.len = Socket->SharedData->SizeOfLocalAddress; 1624 1625 RemoteAddress = HeapAlloc(GlobalHeap, 0, sizeof(*RemoteAddress)); 1626 if (!RemoteAddress) 1627 { 1628 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL); 1629 } 1630 1631 /* Set up Address in SOCKADDR Format */ 1632 RtlCopyMemory (RemoteAddress, 1633 &ListenReceiveData->Address.Address[0].AddressType, 1634 sizeof(*RemoteAddress)); 1635 1636 /* Build Caller ID */ 1637 CallerID.buf = (PVOID)RemoteAddress; 1638 CallerID.len = sizeof(*RemoteAddress); 1639 1640 /* Build Caller Data */ 1641 CallerData.buf = PendingData; 1642 CallerData.len = PendingDataLength; 1643 1644 /* Check if socket supports Conditional Accept */ 1645 if (Socket->SharedData->UseDelayedAcceptance != 0) 1646 { 1647 /* Allocate Buffer for Callee Data */ 1648 CalleeDataBuffer = HeapAlloc(GlobalHeap, 0, 4096); 1649 if (!CalleeDataBuffer) { 1650 return MsafdReturnWithErrno( STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL ); 1651 } 1652 CalleeData.buf = CalleeDataBuffer; 1653 CalleeData.len = 4096; 1654 } 1655 else 1656 { 1657 /* Nothing */ 1658 CalleeData.buf = 0; 1659 CalleeData.len = 0; 1660 } 1661 1662 /* Call the Condition Function */ 1663 CallBack = (lpfnCondition)(&CallerID, 1664 CallerData.buf == NULL ? NULL : &CallerData, 1665 NULL, 1666 NULL, 1667 &CalleeID, 1668 CalleeData.buf == NULL ? NULL : &CalleeData, 1669 &GroupID, 1670 dwCallbackData); 1671 1672 if (((CallBack == CF_ACCEPT) && GroupID) != 0) 1673 { 1674 /* TBD: Check for Validity */ 1675 } 1676 1677 if (CallBack == CF_ACCEPT) 1678 { 1679 if ((Socket->SharedData->ServiceFlags1 & XP1_QOS_SUPPORTED) != 0) 1680 { 1681 /* I don't support this yet */ 1682 } 1683 if (CalleeData.buf) 1684 { 1685 // SockSetConnectData Sockets(SocketID), IOCTL_AFD_SET_CONNECT_DATA, CalleeData.Buffer, CalleeData.BuffSize, 0 1686 } 1687 } 1688 else 1689 { 1690 /* Callback rejected. Build Defer Structure */ 1691 DeferData.SequenceNumber = ListenReceiveData->SequenceNumber; 1692 DeferData.RejectConnection = (CallBack == CF_REJECT); 1693 1694 /* Send IOCTL */ 1695 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle, 1696 SockEvent, 1697 NULL, 1698 NULL, 1699 &IOSB, 1700 IOCTL_AFD_DEFER_ACCEPT, 1701 &DeferData, 1702 sizeof(DeferData), 1703 NULL, 1704 0); 1705 1706 /* Wait for return */ 1707 if (Status == STATUS_PENDING) 1708 { 1709 WaitForSingleObject(SockEvent, INFINITE); 1710 Status = IOSB.Status; 1711 } 1712 1713 NtClose( SockEvent ); 1714 1715 if (!NT_SUCCESS(Status)) 1716 { 1717 return MsafdReturnWithErrno( Status, lpErrno, 0, NULL ); 1718 } 1719 1720 if (CallBack == CF_REJECT ) 1721 { 1722 if (lpErrno) *lpErrno = WSAECONNREFUSED; 1723 return SOCKET_ERROR; 1724 } 1725 else 1726 { 1727 if (lpErrno) *lpErrno = WSAECONNREFUSED; 1728 return SOCKET_ERROR; 1729 } 1730 } 1731 } 1732 1733 /* Create a new Socket */ 1734 AcceptSocket = WSPSocket (Socket->SharedData->AddressFamily, 1735 Socket->SharedData->SocketType, 1736 Socket->SharedData->Protocol, 1737 &Socket->ProtocolInfo, 1738 GroupID, 1739 Socket->SharedData->CreateFlags, 1740 lpErrno); 1741 if (AcceptSocket == INVALID_SOCKET) 1742 return SOCKET_ERROR; 1743 1744 /* Set up the Accept Structure */ 1745 AcceptData.ListenHandle = (HANDLE)AcceptSocket; 1746 AcceptData.SequenceNumber = ListenReceiveData->SequenceNumber; 1747 1748 /* Send IOCTL to Accept */ 1749 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle, 1750 SockEvent, 1751 NULL, 1752 NULL, 1753 &IOSB, 1754 IOCTL_AFD_ACCEPT, 1755 &AcceptData, 1756 sizeof(AcceptData), 1757 NULL, 1758 0); 1759 1760 /* Wait for return */ 1761 if (Status == STATUS_PENDING) 1762 { 1763 WaitForSingleObject(SockEvent, INFINITE); 1764 Status = IOSB.Status; 1765 } 1766 1767 Socket->SharedData->SocketLastError = TranslateNtStatusError(Status); 1768 if (!NT_SUCCESS(Status)) 1769 { 1770 NtClose(SockEvent); 1771 WSPCloseSocket( AcceptSocket, lpErrno ); 1772 return MsafdReturnWithErrno( Status, lpErrno, 0, NULL ); 1773 } 1774 1775 AcceptSocketInfo = GetSocketStructure(AcceptSocket); 1776 if (!AcceptSocketInfo) 1777 { 1778 NtClose(SockEvent); 1779 WSPCloseSocket( AcceptSocket, lpErrno ); 1780 return MsafdReturnWithErrno( STATUS_PROTOCOL_NOT_SUPPORTED, lpErrno, 0, NULL ); 1781 } 1782 1783 AcceptSocketInfo->SharedData->State = SocketConnected; 1784 AcceptSocketInfo->SharedData->ConnectTime = GetCurrentTimeInSeconds(); 1785 1786 /* Return Address in SOCKADDR FORMAT */ 1787 if( SocketAddress ) 1788 { 1789 RtlCopyMemory (SocketAddress, 1790 &ListenReceiveData->Address.Address[0].AddressType, 1791 sizeof(*RemoteAddress)); 1792 if( SocketAddressLength ) 1793 *SocketAddressLength = sizeof(*RemoteAddress); 1794 } 1795 1796 NtClose( SockEvent ); 1797 1798 /* Re-enable Async Event */ 1799 SockReenableAsyncSelectEvent(Socket, FD_ACCEPT); 1800 1801 TRACE("Socket %x\n", AcceptSocket); 1802 1803 if (Status == STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_ACCEPT)) 1804 { 1805 Status = Socket->HelperData->WSHNotify(Socket->HelperContext, 1806 Socket->Handle, 1807 Socket->TdiAddressHandle, 1808 Socket->TdiConnectionHandle, 1809 WSH_NOTIFY_ACCEPT); 1810 1811 if (Status) 1812 { 1813 if (lpErrno) *lpErrno = Status; 1814 return SOCKET_ERROR; 1815 } 1816 } 1817 1818 if (lpErrno) *lpErrno = NO_ERROR; 1819 1820 /* Return Socket */ 1821 return AcceptSocket; 1822 } 1823 1824 int 1825 WSPAPI 1826 WSPConnect(SOCKET Handle, 1827 const struct sockaddr * SocketAddress, 1828 int SocketAddressLength, 1829 LPWSABUF lpCallerData, 1830 LPWSABUF lpCalleeData, 1831 LPQOS lpSQOS, 1832 LPQOS lpGQOS, 1833 LPINT lpErrno) 1834 { 1835 IO_STATUS_BLOCK IOSB; 1836 PAFD_CONNECT_INFO ConnectInfo = NULL; 1837 PSOCKET_INFORMATION Socket; 1838 NTSTATUS Status; 1839 INT Errno; 1840 ULONG ConnectDataLength; 1841 ULONG InConnectDataLength; 1842 INT BindAddressLength; 1843 PSOCKADDR BindAddress; 1844 HANDLE SockEvent; 1845 int SocketDataLength; 1846 1847 TRACE("Called (%lx) %lx:%d\n", Handle, ((const struct sockaddr_in *)SocketAddress)->sin_addr, ((const struct sockaddr_in *)SocketAddress)->sin_port); 1848 1849 /* Get the Socket Structure associate to this Socket*/ 1850 Socket = GetSocketStructure(Handle); 1851 if (!Socket) 1852 { 1853 if (lpErrno) *lpErrno = WSAENOTSOCK; 1854 return SOCKET_ERROR; 1855 } 1856 1857 Status = NtCreateEvent(&SockEvent, 1858 EVENT_ALL_ACCESS, 1859 NULL, 1860 SynchronizationEvent, 1861 FALSE); 1862 1863 if (!NT_SUCCESS(Status)) 1864 return SOCKET_ERROR; 1865 1866 /* Bind us First */ 1867 if (Socket->SharedData->State == SocketOpen) 1868 { 1869 /* Get the Wildcard Address */ 1870 BindAddressLength = Socket->HelperData->MaxWSAddressLength; 1871 BindAddress = HeapAlloc(GetProcessHeap(), 0, BindAddressLength); 1872 if (!BindAddress) 1873 { 1874 NtClose(SockEvent); 1875 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL); 1876 } 1877 Socket->HelperData->WSHGetWildcardSockaddr (Socket->HelperContext, 1878 BindAddress, 1879 &BindAddressLength); 1880 /* Bind it */ 1881 if (WSPBind(Handle, BindAddress, BindAddressLength, lpErrno) == SOCKET_ERROR) 1882 return SOCKET_ERROR; 1883 } 1884 1885 /* Set the Connect Data */ 1886 if (lpCallerData != NULL) 1887 { 1888 ConnectDataLength = lpCallerData->len; 1889 Status = NtDeviceIoControlFile((HANDLE)Handle, 1890 SockEvent, 1891 NULL, 1892 NULL, 1893 &IOSB, 1894 IOCTL_AFD_SET_CONNECT_DATA, 1895 lpCallerData->buf, 1896 ConnectDataLength, 1897 NULL, 1898 0); 1899 /* Wait for return */ 1900 if (Status == STATUS_PENDING) 1901 { 1902 WaitForSingleObject(SockEvent, INFINITE); 1903 Status = IOSB.Status; 1904 } 1905 1906 if (Status != STATUS_SUCCESS) 1907 goto notify; 1908 } 1909 1910 /* Calculate the size of SocketAddress->sa_data */ 1911 SocketDataLength = SocketAddressLength - FIELD_OFFSET(struct sockaddr, sa_data); 1912 1913 /* Allocate a connection info buffer with SocketDataLength bytes of payload */ 1914 ConnectInfo = HeapAlloc(GetProcessHeap(), 0, 1915 FIELD_OFFSET(AFD_CONNECT_INFO, 1916 RemoteAddress.Address[0].Address[SocketDataLength])); 1917 if (!ConnectInfo) 1918 { 1919 Status = STATUS_INSUFFICIENT_RESOURCES; 1920 goto notify; 1921 } 1922 1923 /* Set up Address in TDI Format */ 1924 ConnectInfo->RemoteAddress.TAAddressCount = 1; 1925 ConnectInfo->RemoteAddress.Address[0].AddressLength = SocketDataLength; 1926 ConnectInfo->RemoteAddress.Address[0].AddressType = SocketAddress->sa_family; 1927 RtlCopyMemory(ConnectInfo->RemoteAddress.Address[0].Address, 1928 SocketAddress->sa_data, 1929 SocketDataLength); 1930 1931 /* 1932 * Disable FD_WRITE and FD_CONNECT 1933 * The latter fixes a race condition where the FD_CONNECT is re-enabled 1934 * at the end of this function right after the Async Thread disables it. 1935 * This should only happen at the *next* WSPConnect 1936 */ 1937 if (Socket->SharedData->AsyncEvents & FD_CONNECT) 1938 { 1939 Socket->SharedData->AsyncDisabledEvents |= FD_CONNECT | FD_WRITE; 1940 } 1941 1942 /* Tell AFD that we want Connection Data back, have it allocate a buffer */ 1943 if (lpCalleeData != NULL) 1944 { 1945 InConnectDataLength = lpCalleeData->len; 1946 Status = NtDeviceIoControlFile((HANDLE)Handle, 1947 SockEvent, 1948 NULL, 1949 NULL, 1950 &IOSB, 1951 IOCTL_AFD_SET_CONNECT_DATA_SIZE, 1952 &InConnectDataLength, 1953 sizeof(InConnectDataLength), 1954 NULL, 1955 0); 1956 1957 /* Wait for return */ 1958 if (Status == STATUS_PENDING) 1959 { 1960 WaitForSingleObject(SockEvent, INFINITE); 1961 Status = IOSB.Status; 1962 } 1963 1964 if (Status != STATUS_SUCCESS) 1965 goto notify; 1966 } 1967 1968 /* AFD doesn't seem to care if these are invalid, but let's 0 them anyways */ 1969 ConnectInfo->Root = 0; 1970 ConnectInfo->UseSAN = FALSE; 1971 ConnectInfo->Unknown = 0; 1972 1973 /* FIXME: Handle Async Connect */ 1974 if (Socket->SharedData->NonBlocking) 1975 { 1976 ERR("Async Connect UNIMPLEMENTED!\n"); 1977 } 1978 1979 /* Send IOCTL */ 1980 Status = NtDeviceIoControlFile((HANDLE)Handle, 1981 SockEvent, 1982 NULL, 1983 NULL, 1984 &IOSB, 1985 IOCTL_AFD_CONNECT, 1986 ConnectInfo, 1987 0x22, 1988 NULL, 1989 0); 1990 /* Wait for return */ 1991 if (Status == STATUS_PENDING) 1992 { 1993 WaitForSingleObject(SockEvent, INFINITE); 1994 Status = IOSB.Status; 1995 } 1996 1997 Socket->SharedData->SocketLastError = TranslateNtStatusError(Status); 1998 if (Status != STATUS_SUCCESS) 1999 goto notify; 2000 2001 Socket->SharedData->State = SocketConnected; 2002 Socket->TdiConnectionHandle = (HANDLE)IOSB.Information; 2003 Socket->SharedData->ConnectTime = GetCurrentTimeInSeconds(); 2004 2005 /* Get any pending connect data */ 2006 if (lpCalleeData != NULL) 2007 { 2008 Status = NtDeviceIoControlFile((HANDLE)Handle, 2009 SockEvent, 2010 NULL, 2011 NULL, 2012 &IOSB, 2013 IOCTL_AFD_GET_CONNECT_DATA, 2014 NULL, 2015 0, 2016 lpCalleeData->buf, 2017 lpCalleeData->len); 2018 /* Wait for return */ 2019 if (Status == STATUS_PENDING) 2020 { 2021 WaitForSingleObject(SockEvent, INFINITE); 2022 Status = IOSB.Status; 2023 } 2024 } 2025 2026 TRACE("Ending %lx\n", IOSB.Status); 2027 2028 notify: 2029 if (ConnectInfo) HeapFree(GetProcessHeap(), 0, ConnectInfo); 2030 2031 /* Re-enable Async Event */ 2032 SockReenableAsyncSelectEvent(Socket, FD_WRITE); 2033 2034 /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */ 2035 SockReenableAsyncSelectEvent(Socket, FD_CONNECT); 2036 2037 NtClose(SockEvent); 2038 2039 if (Status == STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_CONNECT)) 2040 { 2041 Errno = Socket->HelperData->WSHNotify(Socket->HelperContext, 2042 Socket->Handle, 2043 Socket->TdiAddressHandle, 2044 Socket->TdiConnectionHandle, 2045 WSH_NOTIFY_CONNECT); 2046 2047 if (Errno) 2048 { 2049 if (lpErrno) *lpErrno = Errno; 2050 return SOCKET_ERROR; 2051 } 2052 } 2053 else if (Status != STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_CONNECT_ERROR)) 2054 { 2055 Errno = Socket->HelperData->WSHNotify(Socket->HelperContext, 2056 Socket->Handle, 2057 Socket->TdiAddressHandle, 2058 Socket->TdiConnectionHandle, 2059 WSH_NOTIFY_CONNECT_ERROR); 2060 2061 if (Errno) 2062 { 2063 if (lpErrno) *lpErrno = Errno; 2064 return SOCKET_ERROR; 2065 } 2066 } 2067 2068 return MsafdReturnWithErrno(Status, lpErrno, 0, NULL); 2069 } 2070 int 2071 WSPAPI 2072 WSPShutdown(SOCKET Handle, 2073 int HowTo, 2074 LPINT lpErrno) 2075 2076 { 2077 IO_STATUS_BLOCK IOSB; 2078 AFD_DISCONNECT_INFO DisconnectInfo; 2079 PSOCKET_INFORMATION Socket = NULL; 2080 NTSTATUS Status; 2081 HANDLE SockEvent; 2082 2083 TRACE("Called\n"); 2084 2085 /* Get the Socket Structure associate to this Socket*/ 2086 Socket = GetSocketStructure(Handle); 2087 if (!Socket) 2088 { 2089 if (lpErrno) *lpErrno = WSAENOTSOCK; 2090 return SOCKET_ERROR; 2091 } 2092 2093 Status = NtCreateEvent(&SockEvent, 2094 EVENT_ALL_ACCESS, 2095 NULL, 2096 SynchronizationEvent, 2097 FALSE); 2098 2099 if( !NT_SUCCESS(Status) ) 2100 return SOCKET_ERROR; 2101 2102 /* Set AFD Disconnect Type */ 2103 switch (HowTo) 2104 { 2105 case SD_RECEIVE: 2106 DisconnectInfo.DisconnectType = AFD_DISCONNECT_RECV; 2107 Socket->SharedData->ReceiveShutdown = TRUE; 2108 break; 2109 case SD_SEND: 2110 DisconnectInfo.DisconnectType= AFD_DISCONNECT_SEND; 2111 Socket->SharedData->SendShutdown = TRUE; 2112 break; 2113 case SD_BOTH: 2114 DisconnectInfo.DisconnectType = AFD_DISCONNECT_RECV | AFD_DISCONNECT_SEND; 2115 Socket->SharedData->ReceiveShutdown = TRUE; 2116 Socket->SharedData->SendShutdown = TRUE; 2117 break; 2118 } 2119 2120 DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(-1000000); 2121 2122 /* Send IOCTL */ 2123 Status = NtDeviceIoControlFile((HANDLE)Handle, 2124 SockEvent, 2125 NULL, 2126 NULL, 2127 &IOSB, 2128 IOCTL_AFD_DISCONNECT, 2129 &DisconnectInfo, 2130 sizeof(DisconnectInfo), 2131 NULL, 2132 0); 2133 2134 /* Wait for return */ 2135 if (Status == STATUS_PENDING) 2136 { 2137 WaitForSingleObject(SockEvent, INFINITE); 2138 Status = IOSB.Status; 2139 } 2140 2141 TRACE("Ending\n"); 2142 2143 NtClose( SockEvent ); 2144 2145 Socket->SharedData->SocketLastError = TranslateNtStatusError(Status); 2146 return MsafdReturnWithErrno( Status, lpErrno, 0, NULL ); 2147 } 2148 2149 2150 INT 2151 WSPAPI 2152 WSPGetSockName(IN SOCKET Handle, 2153 OUT LPSOCKADDR Name, 2154 IN OUT LPINT NameLength, 2155 OUT LPINT lpErrno) 2156 { 2157 IO_STATUS_BLOCK IOSB; 2158 ULONG TdiAddressSize; 2159 PTDI_ADDRESS_INFO TdiAddress; 2160 PTRANSPORT_ADDRESS SocketAddress; 2161 PSOCKET_INFORMATION Socket = NULL; 2162 NTSTATUS Status; 2163 HANDLE SockEvent; 2164 2165 /* Get the Socket Structure associate to this Socket*/ 2166 Socket = GetSocketStructure(Handle); 2167 if (!Socket) 2168 { 2169 if (lpErrno) *lpErrno = WSAENOTSOCK; 2170 return SOCKET_ERROR; 2171 } 2172 2173 if (!Name || !NameLength) 2174 { 2175 if (lpErrno) *lpErrno = WSAEFAULT; 2176 return SOCKET_ERROR; 2177 } 2178 2179 Status = NtCreateEvent(&SockEvent, 2180 EVENT_ALL_ACCESS, 2181 NULL, 2182 SynchronizationEvent, 2183 FALSE); 2184 2185 if( !NT_SUCCESS(Status) ) 2186 return SOCKET_ERROR; 2187 2188 /* Allocate a buffer for the address */ 2189 TdiAddressSize = 2190 sizeof(TRANSPORT_ADDRESS) + Socket->SharedData->SizeOfLocalAddress; 2191 TdiAddress = HeapAlloc(GlobalHeap, 0, TdiAddressSize); 2192 2193 if ( TdiAddress == NULL ) 2194 { 2195 NtClose( SockEvent ); 2196 if (lpErrno) *lpErrno = WSAENOBUFS; 2197 return SOCKET_ERROR; 2198 } 2199 2200 SocketAddress = &TdiAddress->Address; 2201 2202 /* Send IOCTL */ 2203 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle, 2204 SockEvent, 2205 NULL, 2206 NULL, 2207 &IOSB, 2208 IOCTL_AFD_GET_SOCK_NAME, 2209 NULL, 2210 0, 2211 TdiAddress, 2212 TdiAddressSize); 2213 2214 /* Wait for return */ 2215 if (Status == STATUS_PENDING) 2216 { 2217 WaitForSingleObject(SockEvent, INFINITE); 2218 Status = IOSB.Status; 2219 } 2220 2221 NtClose( SockEvent ); 2222 2223 if (NT_SUCCESS(Status)) 2224 { 2225 if (*NameLength >= Socket->SharedData->SizeOfLocalAddress) 2226 { 2227 Name->sa_family = SocketAddress->Address[0].AddressType; 2228 RtlCopyMemory (Name->sa_data, 2229 SocketAddress->Address[0].Address, 2230 SocketAddress->Address[0].AddressLength); 2231 *NameLength = Socket->SharedData->SizeOfLocalAddress; 2232 TRACE("NameLength %d Address: %x Port %x\n", 2233 *NameLength, ((struct sockaddr_in *)Name)->sin_addr.s_addr, 2234 ((struct sockaddr_in *)Name)->sin_port); 2235 HeapFree(GlobalHeap, 0, TdiAddress); 2236 return 0; 2237 } 2238 else 2239 { 2240 HeapFree(GlobalHeap, 0, TdiAddress); 2241 if (lpErrno) *lpErrno = WSAEFAULT; 2242 return SOCKET_ERROR; 2243 } 2244 } 2245 2246 HeapFree(GlobalHeap, 0, TdiAddress); 2247 2248 return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL ); 2249 } 2250 2251 2252 INT 2253 WSPAPI 2254 WSPGetPeerName(IN SOCKET s, 2255 OUT LPSOCKADDR Name, 2256 IN OUT LPINT NameLength, 2257 OUT LPINT lpErrno) 2258 { 2259 IO_STATUS_BLOCK IOSB; 2260 ULONG TdiAddressSize; 2261 PTRANSPORT_ADDRESS SocketAddress; 2262 PSOCKET_INFORMATION Socket = NULL; 2263 NTSTATUS Status; 2264 HANDLE SockEvent; 2265 2266 /* Get the Socket Structure associate to this Socket*/ 2267 Socket = GetSocketStructure(s); 2268 if (!Socket) 2269 { 2270 if (lpErrno) *lpErrno = WSAENOTSOCK; 2271 return SOCKET_ERROR; 2272 } 2273 2274 if (Socket->SharedData->State != SocketConnected) 2275 { 2276 if (lpErrno) *lpErrno = WSAENOTCONN; 2277 return SOCKET_ERROR; 2278 } 2279 2280 if (!Name || !NameLength) 2281 { 2282 if (lpErrno) *lpErrno = WSAEFAULT; 2283 return SOCKET_ERROR; 2284 } 2285 2286 Status = NtCreateEvent(&SockEvent, 2287 EVENT_ALL_ACCESS, 2288 NULL, 2289 SynchronizationEvent, 2290 FALSE); 2291 2292 if( !NT_SUCCESS(Status) ) 2293 return SOCKET_ERROR; 2294 2295 /* Allocate a buffer for the address */ 2296 TdiAddressSize = sizeof(TRANSPORT_ADDRESS) + Socket->SharedData->SizeOfRemoteAddress; 2297 SocketAddress = HeapAlloc(GlobalHeap, 0, TdiAddressSize); 2298 2299 if ( SocketAddress == NULL ) 2300 { 2301 NtClose( SockEvent ); 2302 if (lpErrno) *lpErrno = WSAENOBUFS; 2303 return SOCKET_ERROR; 2304 } 2305 2306 /* Send IOCTL */ 2307 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle, 2308 SockEvent, 2309 NULL, 2310 NULL, 2311 &IOSB, 2312 IOCTL_AFD_GET_PEER_NAME, 2313 NULL, 2314 0, 2315 SocketAddress, 2316 TdiAddressSize); 2317 2318 /* Wait for return */ 2319 if (Status == STATUS_PENDING) 2320 { 2321 WaitForSingleObject(SockEvent, INFINITE); 2322 Status = IOSB.Status; 2323 } 2324 2325 NtClose( SockEvent ); 2326 2327 if (NT_SUCCESS(Status)) 2328 { 2329 if (*NameLength >= Socket->SharedData->SizeOfRemoteAddress) 2330 { 2331 Name->sa_family = SocketAddress->Address[0].AddressType; 2332 RtlCopyMemory (Name->sa_data, 2333 SocketAddress->Address[0].Address, 2334 SocketAddress->Address[0].AddressLength); 2335 *NameLength = Socket->SharedData->SizeOfRemoteAddress; 2336 TRACE("NameLength %d Address: %x Port %x\n", 2337 *NameLength, ((struct sockaddr_in *)Name)->sin_addr.s_addr, 2338 ((struct sockaddr_in *)Name)->sin_port); 2339 HeapFree(GlobalHeap, 0, SocketAddress); 2340 return 0; 2341 } 2342 else 2343 { 2344 HeapFree(GlobalHeap, 0, SocketAddress); 2345 if (lpErrno) *lpErrno = WSAEFAULT; 2346 return SOCKET_ERROR; 2347 } 2348 } 2349 2350 HeapFree(GlobalHeap, 0, SocketAddress); 2351 2352 return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL ); 2353 } 2354 2355 INT 2356 WSPAPI 2357 WSPIoctl(IN SOCKET Handle, 2358 IN DWORD dwIoControlCode, 2359 IN LPVOID lpvInBuffer, 2360 IN DWORD cbInBuffer, 2361 OUT LPVOID lpvOutBuffer, 2362 IN DWORD cbOutBuffer, 2363 OUT LPDWORD lpcbBytesReturned, 2364 IN LPWSAOVERLAPPED lpOverlapped, 2365 IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, 2366 IN LPWSATHREADID lpThreadId, 2367 OUT LPINT lpErrno) 2368 { 2369 PSOCKET_INFORMATION Socket = NULL; 2370 BOOL NeedsCompletion = lpOverlapped != NULL; 2371 BOOLEAN NonBlocking; 2372 INT Errno = NO_ERROR, Ret = SOCKET_ERROR; 2373 DWORD cbRet = 0; 2374 2375 /* Get the Socket Structure associate to this Socket*/ 2376 Socket = GetSocketStructure(Handle); 2377 if (!Socket) 2378 { 2379 if(lpErrno) 2380 *lpErrno = WSAENOTSOCK; 2381 return SOCKET_ERROR; 2382 } 2383 2384 if (!lpcbBytesReturned && !lpOverlapped) 2385 { 2386 if(lpErrno) 2387 *lpErrno = WSAEFAULT; 2388 return SOCKET_ERROR; 2389 } 2390 2391 switch( dwIoControlCode ) 2392 { 2393 case FIONBIO: 2394 if( cbInBuffer < sizeof(INT) || IS_INTRESOURCE(lpvInBuffer) ) 2395 { 2396 Errno = WSAEFAULT; 2397 break; 2398 } 2399 NonBlocking = *((PULONG)lpvInBuffer) ? TRUE : FALSE; 2400 /* Don't allow to go in blocking mode if WSPAsyncSelect or WSPEventSelect is pending */ 2401 if (!NonBlocking) 2402 { 2403 /* If there is an WSPAsyncSelect pending, fail with WSAEINVAL */ 2404 if (Socket->SharedData->AsyncEvents & (~Socket->SharedData->AsyncDisabledEvents)) 2405 { 2406 Errno = WSAEINVAL; 2407 break; 2408 } 2409 /* If there is an WSPEventSelect pending, fail with WSAEINVAL */ 2410 if (Socket->NetworkEvents) 2411 { 2412 Errno = WSAEINVAL; 2413 break; 2414 } 2415 } 2416 Socket->SharedData->NonBlocking = NonBlocking ? 1 : 0; 2417 NeedsCompletion = FALSE; 2418 Errno = SetSocketInformation(Socket, AFD_INFO_BLOCKING_MODE, &NonBlocking, NULL, NULL, lpOverlapped, lpCompletionRoutine); 2419 if (Errno == NO_ERROR) 2420 Ret = NO_ERROR; 2421 break; 2422 case FIONREAD: 2423 if (IS_INTRESOURCE(lpvOutBuffer) || cbOutBuffer == 0) 2424 { 2425 cbRet = sizeof(ULONG); 2426 Errno = WSAEFAULT; 2427 break; 2428 } 2429 if (cbOutBuffer < sizeof(ULONG)) 2430 { 2431 Errno = WSAEINVAL; 2432 break; 2433 } 2434 NeedsCompletion = FALSE; 2435 Errno = GetSocketInformation(Socket, AFD_INFO_RECEIVE_CONTENT_SIZE, NULL, (PULONG)lpvOutBuffer, NULL, lpOverlapped, lpCompletionRoutine); 2436 if (Errno == NO_ERROR) 2437 { 2438 cbRet = sizeof(ULONG); 2439 Ret = NO_ERROR; 2440 } 2441 break; 2442 case SIOCATMARK: 2443 if (IS_INTRESOURCE(lpvOutBuffer) || cbOutBuffer == 0) 2444 { 2445 cbRet = sizeof(BOOL); 2446 Errno = WSAEFAULT; 2447 break; 2448 } 2449 if (cbOutBuffer < sizeof(BOOL)) 2450 { 2451 Errno = WSAEINVAL; 2452 break; 2453 } 2454 if (Socket->SharedData->SocketType != SOCK_STREAM) 2455 { 2456 Errno = WSAEINVAL; 2457 break; 2458 } 2459 2460 /* FIXME: Return false if OOBINLINE is true for now 2461 We should MSG_PEEK|MSG_OOB check with driver 2462 */ 2463 *(BOOL*)lpvOutBuffer = !Socket->SharedData->OobInline; 2464 2465 cbRet = sizeof(BOOL); 2466 Errno = NO_ERROR; 2467 Ret = NO_ERROR; 2468 break; 2469 case SIO_GET_EXTENSION_FUNCTION_POINTER: 2470 if (cbOutBuffer == 0) 2471 { 2472 cbRet = sizeof(PVOID); 2473 Errno = WSAEFAULT; 2474 break; 2475 } 2476 2477 if (cbInBuffer < sizeof(GUID) || 2478 cbOutBuffer < sizeof(PVOID)) 2479 { 2480 Errno = WSAEINVAL; 2481 break; 2482 } 2483 2484 { 2485 GUID AcceptExGUID = WSAID_ACCEPTEX; 2486 GUID ConnectExGUID = WSAID_CONNECTEX; 2487 GUID DisconnectExGUID = WSAID_DISCONNECTEX; 2488 GUID GetAcceptExSockaddrsGUID = WSAID_GETACCEPTEXSOCKADDRS; 2489 2490 if (IsEqualGUID(&AcceptExGUID, lpvInBuffer)) 2491 { 2492 *((PVOID *)lpvOutBuffer) = WSPAcceptEx; 2493 cbRet = sizeof(PVOID); 2494 Errno = NO_ERROR; 2495 Ret = NO_ERROR; 2496 } 2497 else if (IsEqualGUID(&ConnectExGUID, lpvInBuffer)) 2498 { 2499 *((PVOID *)lpvOutBuffer) = WSPConnectEx; 2500 cbRet = sizeof(PVOID); 2501 Errno = NO_ERROR; 2502 Ret = NO_ERROR; 2503 } 2504 else if (IsEqualGUID(&DisconnectExGUID, lpvInBuffer)) 2505 { 2506 *((PVOID *)lpvOutBuffer) = WSPDisconnectEx; 2507 cbRet = sizeof(PVOID); 2508 Errno = NO_ERROR; 2509 Ret = NO_ERROR; 2510 } 2511 else if (IsEqualGUID(&GetAcceptExSockaddrsGUID, lpvInBuffer)) 2512 { 2513 *((PVOID *)lpvOutBuffer) = WSPGetAcceptExSockaddrs; 2514 cbRet = sizeof(PVOID); 2515 Errno = NO_ERROR; 2516 Ret = NO_ERROR; 2517 } 2518 else 2519 { 2520 ERR("Querying unknown extension function: %x\n", ((GUID*)lpvInBuffer)->Data1); 2521 Errno = WSAEOPNOTSUPP; 2522 } 2523 } 2524 2525 break; 2526 case SIO_ADDRESS_LIST_QUERY: 2527 if (IS_INTRESOURCE(lpvOutBuffer) || cbOutBuffer == 0) 2528 { 2529 cbRet = sizeof(SOCKET_ADDRESS_LIST) + sizeof(Socket->SharedData->WSLocalAddress); 2530 Errno = WSAEFAULT; 2531 break; 2532 } 2533 if (cbOutBuffer < sizeof(INT)) 2534 { 2535 Errno = WSAEINVAL; 2536 break; 2537 } 2538 2539 cbRet = sizeof(SOCKET_ADDRESS_LIST) + sizeof(Socket->SharedData->WSLocalAddress); 2540 2541 ((SOCKET_ADDRESS_LIST*)lpvOutBuffer)->iAddressCount = 1; 2542 2543 if (cbOutBuffer < (sizeof(SOCKET_ADDRESS_LIST) + sizeof(Socket->SharedData->WSLocalAddress))) 2544 { 2545 Errno = WSAEFAULT; 2546 break; 2547 } 2548 2549 ((SOCKET_ADDRESS_LIST*)lpvOutBuffer)->Address[0].iSockaddrLength = sizeof(Socket->SharedData->WSLocalAddress); 2550 ((SOCKET_ADDRESS_LIST*)lpvOutBuffer)->Address[0].lpSockaddr = &Socket->SharedData->WSLocalAddress; 2551 2552 Errno = NO_ERROR; 2553 Ret = NO_ERROR; 2554 break; 2555 default: 2556 Errno = Socket->HelperData->WSHIoctl(Socket->HelperContext, 2557 Handle, 2558 Socket->TdiAddressHandle, 2559 Socket->TdiConnectionHandle, 2560 dwIoControlCode, 2561 lpvInBuffer, 2562 cbInBuffer, 2563 lpvOutBuffer, 2564 cbOutBuffer, 2565 &cbRet, 2566 lpOverlapped, 2567 lpCompletionRoutine, 2568 &NeedsCompletion); 2569 2570 if (Errno == NO_ERROR) 2571 Ret = NO_ERROR; 2572 break; 2573 } 2574 if (lpOverlapped && NeedsCompletion) 2575 { 2576 lpOverlapped->Internal = Errno; 2577 lpOverlapped->InternalHigh = cbRet; 2578 if (lpCompletionRoutine != NULL) 2579 { 2580 lpCompletionRoutine(Errno, cbRet, lpOverlapped, 0); 2581 } 2582 if (lpOverlapped->hEvent) 2583 SetEvent(lpOverlapped->hEvent); 2584 if (!PostQueuedCompletionStatus((HANDLE)Handle, cbRet, 0, lpOverlapped)) 2585 { 2586 ERR("PostQueuedCompletionStatus failed %d\n", GetLastError()); 2587 } 2588 return NO_ERROR; 2589 } 2590 if (lpErrno) 2591 *lpErrno = Errno; 2592 if (lpcbBytesReturned) 2593 *lpcbBytesReturned = cbRet; 2594 return Ret; 2595 } 2596 2597 2598 INT 2599 WSPAPI 2600 WSPGetSockOpt(IN SOCKET Handle, 2601 IN INT Level, 2602 IN INT OptionName, 2603 OUT CHAR FAR* OptionValue, 2604 IN OUT LPINT OptionLength, 2605 OUT LPINT lpErrno) 2606 { 2607 PSOCKET_INFORMATION Socket = NULL; 2608 PVOID Buffer; 2609 INT BufferSize; 2610 BOOL BoolBuffer; 2611 DWORD DwordBuffer; 2612 INT Errno; 2613 2614 TRACE("Called\n"); 2615 2616 /* Get the Socket Structure associate to this Socket*/ 2617 Socket = GetSocketStructure(Handle); 2618 if (Socket == NULL) 2619 { 2620 if (lpErrno) *lpErrno = WSAENOTSOCK; 2621 return SOCKET_ERROR; 2622 } 2623 if (!OptionLength || !OptionValue) 2624 { 2625 if (lpErrno) *lpErrno = WSAEFAULT; 2626 return SOCKET_ERROR; 2627 } 2628 2629 switch (Level) 2630 { 2631 case SOL_SOCKET: 2632 switch (OptionName) 2633 { 2634 case SO_TYPE: 2635 Buffer = &Socket->SharedData->SocketType; 2636 BufferSize = sizeof(INT); 2637 break; 2638 2639 case SO_RCVBUF: 2640 Buffer = &Socket->SharedData->SizeOfRecvBuffer; 2641 BufferSize = sizeof(ULONG); 2642 break; 2643 2644 case SO_SNDBUF: 2645 Buffer = &Socket->SharedData->SizeOfSendBuffer; 2646 BufferSize = sizeof(ULONG); 2647 break; 2648 2649 case SO_ACCEPTCONN: 2650 BoolBuffer = Socket->SharedData->Listening; 2651 Buffer = &BoolBuffer; 2652 BufferSize = sizeof(BOOL); 2653 break; 2654 2655 case SO_BROADCAST: 2656 BoolBuffer = Socket->SharedData->Broadcast; 2657 Buffer = &BoolBuffer; 2658 BufferSize = sizeof(BOOL); 2659 break; 2660 2661 case SO_DEBUG: 2662 BoolBuffer = Socket->SharedData->Debug; 2663 Buffer = &BoolBuffer; 2664 BufferSize = sizeof(BOOL); 2665 break; 2666 2667 case SO_DONTLINGER: 2668 BoolBuffer = (Socket->SharedData->LingerData.l_onoff == 0); 2669 Buffer = &BoolBuffer; 2670 BufferSize = sizeof(BOOL); 2671 break; 2672 2673 case SO_LINGER: 2674 if (Socket->SharedData->SocketType == SOCK_DGRAM) 2675 { 2676 if (lpErrno) *lpErrno = WSAENOPROTOOPT; 2677 return SOCKET_ERROR; 2678 } 2679 Buffer = &Socket->SharedData->LingerData; 2680 BufferSize = sizeof(struct linger); 2681 break; 2682 2683 case SO_OOBINLINE: 2684 BoolBuffer = (Socket->SharedData->OobInline != 0); 2685 Buffer = &BoolBuffer; 2686 BufferSize = sizeof(BOOL); 2687 break; 2688 2689 case SO_KEEPALIVE: 2690 case SO_DONTROUTE: 2691 /* These guys go directly to the helper */ 2692 goto SendToHelper; 2693 2694 case SO_CONDITIONAL_ACCEPT: 2695 BoolBuffer = (Socket->SharedData->UseDelayedAcceptance != 0); 2696 Buffer = &BoolBuffer; 2697 BufferSize = sizeof(BOOL); 2698 break; 2699 2700 case SO_REUSEADDR: 2701 BoolBuffer = (Socket->SharedData->ReuseAddresses != 0); 2702 Buffer = &BoolBuffer; 2703 BufferSize = sizeof(BOOL); 2704 break; 2705 2706 case SO_EXCLUSIVEADDRUSE: 2707 BoolBuffer = (Socket->SharedData->ExclusiveAddressUse != 0); 2708 Buffer = &BoolBuffer; 2709 BufferSize = sizeof(BOOL); 2710 break; 2711 2712 case SO_ERROR: 2713 Buffer = &Socket->SharedData->SocketLastError; 2714 BufferSize = sizeof(INT); 2715 break; 2716 2717 case SO_CONNECT_TIME: 2718 DwordBuffer = GetCurrentTimeInSeconds() - Socket->SharedData->ConnectTime; 2719 Buffer = &DwordBuffer; 2720 BufferSize = sizeof(DWORD); 2721 break; 2722 2723 case SO_SNDTIMEO: 2724 Buffer = &Socket->SharedData->SendTimeout; 2725 BufferSize = sizeof(DWORD); 2726 break; 2727 case SO_RCVTIMEO: 2728 Buffer = &Socket->SharedData->RecvTimeout; 2729 BufferSize = sizeof(DWORD); 2730 break; 2731 case SO_PROTOCOL_INFOW: 2732 Buffer = &Socket->ProtocolInfo; 2733 BufferSize = sizeof(Socket->ProtocolInfo); 2734 break; 2735 2736 case SO_GROUP_ID: 2737 case SO_GROUP_PRIORITY: 2738 case SO_MAX_MSG_SIZE: 2739 2740 default: 2741 DbgPrint("MSAFD: Get unknown optname %x\n", OptionName); 2742 if (lpErrno) *lpErrno = WSAENOPROTOOPT; 2743 return SOCKET_ERROR; 2744 } 2745 2746 if (*OptionLength < BufferSize) 2747 { 2748 if (lpErrno) *lpErrno = WSAEFAULT; 2749 *OptionLength = BufferSize; 2750 return SOCKET_ERROR; 2751 } 2752 RtlCopyMemory(OptionValue, Buffer, BufferSize); 2753 2754 return 0; 2755 2756 default: 2757 if (lpErrno) *lpErrno = WSAEINVAL; 2758 return SOCKET_ERROR; 2759 } 2760 2761 SendToHelper: 2762 Errno = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, 2763 Handle, 2764 Socket->TdiAddressHandle, 2765 Socket->TdiConnectionHandle, 2766 Level, 2767 OptionName, 2768 OptionValue, 2769 (LPINT)OptionLength); 2770 if (lpErrno) *lpErrno = Errno; 2771 return (Errno == NO_ERROR) ? NO_ERROR : SOCKET_ERROR; 2772 } 2773 2774 INT 2775 WSPAPI 2776 WSPSetSockOpt( 2777 IN SOCKET s, 2778 IN INT level, 2779 IN INT optname, 2780 IN CONST CHAR FAR* optval, 2781 IN INT optlen, 2782 OUT LPINT lpErrno) 2783 { 2784 PSOCKET_INFORMATION Socket; 2785 INT Errno; 2786 2787 /* Get the Socket Structure associate to this Socket*/ 2788 Socket = GetSocketStructure(s); 2789 if (Socket == NULL) 2790 { 2791 if (lpErrno) *lpErrno = WSAENOTSOCK; 2792 return SOCKET_ERROR; 2793 } 2794 if (!optval) 2795 { 2796 if (lpErrno) *lpErrno = WSAEFAULT; 2797 return SOCKET_ERROR; 2798 } 2799 2800 2801 /* FIXME: We should handle some more cases here */ 2802 if (level == SOL_SOCKET) 2803 { 2804 switch (optname) 2805 { 2806 case SO_BROADCAST: 2807 if (optlen < sizeof(BOOL)) 2808 { 2809 if (lpErrno) *lpErrno = WSAEFAULT; 2810 return SOCKET_ERROR; 2811 } 2812 Socket->SharedData->Broadcast = (*optval != 0) ? 1 : 0; 2813 return NO_ERROR; 2814 2815 case SO_OOBINLINE: 2816 if (optlen < sizeof(BOOL)) 2817 { 2818 if (lpErrno) *lpErrno = WSAEFAULT; 2819 return SOCKET_ERROR; 2820 } 2821 Socket->SharedData->OobInline = (*optval != 0) ? 1 : 0; 2822 return NO_ERROR; 2823 2824 case SO_DONTLINGER: 2825 if (optlen < sizeof(BOOL)) 2826 { 2827 if (lpErrno) *lpErrno = WSAEFAULT; 2828 return SOCKET_ERROR; 2829 } 2830 Socket->SharedData->LingerData.l_onoff = (*optval != 0) ? 0 : 1; 2831 return NO_ERROR; 2832 2833 case SO_REUSEADDR: 2834 if (optlen < sizeof(BOOL)) 2835 { 2836 if (lpErrno) *lpErrno = WSAEFAULT; 2837 return SOCKET_ERROR; 2838 } 2839 Socket->SharedData->ReuseAddresses = (*optval != 0) ? 1 : 0; 2840 return NO_ERROR; 2841 2842 case SO_EXCLUSIVEADDRUSE: 2843 if (optlen < sizeof(BOOL)) 2844 { 2845 if (lpErrno) *lpErrno = WSAEFAULT; 2846 return SOCKET_ERROR; 2847 } 2848 Socket->SharedData->ExclusiveAddressUse = (*optval != 0) ? 1 : 0; 2849 return NO_ERROR; 2850 2851 case SO_LINGER: 2852 if (optlen < sizeof(struct linger)) 2853 { 2854 if (lpErrno) *lpErrno = WSAEFAULT; 2855 return SOCKET_ERROR; 2856 } 2857 RtlCopyMemory(&Socket->SharedData->LingerData, 2858 optval, 2859 sizeof(struct linger)); 2860 return NO_ERROR; 2861 2862 case SO_SNDBUF: 2863 if (optlen < sizeof(ULONG)) 2864 { 2865 if (lpErrno) *lpErrno = WSAEFAULT; 2866 return SOCKET_ERROR; 2867 } 2868 2869 SetSocketInformation(Socket, 2870 AFD_INFO_SEND_WINDOW_SIZE, 2871 NULL, 2872 (PULONG)optval, 2873 NULL, 2874 NULL, 2875 NULL); 2876 GetSocketInformation(Socket, 2877 AFD_INFO_SEND_WINDOW_SIZE, 2878 NULL, 2879 &Socket->SharedData->SizeOfSendBuffer, 2880 NULL, 2881 NULL, 2882 NULL); 2883 2884 return NO_ERROR; 2885 2886 case SO_RCVBUF: 2887 if (optlen < sizeof(ULONG)) 2888 { 2889 if (lpErrno) *lpErrno = WSAEFAULT; 2890 return SOCKET_ERROR; 2891 } 2892 2893 /* FIXME: We should not have to limit the packet receive buffer size like this. workaround for CORE-15804 */ 2894 if (*(PULONG)optval > 0x2000) 2895 *(PULONG)optval = 0x2000; 2896 2897 SetSocketInformation(Socket, 2898 AFD_INFO_RECEIVE_WINDOW_SIZE, 2899 NULL, 2900 (PULONG)optval, 2901 NULL, 2902 NULL, 2903 NULL); 2904 GetSocketInformation(Socket, 2905 AFD_INFO_RECEIVE_WINDOW_SIZE, 2906 NULL, 2907 &Socket->SharedData->SizeOfRecvBuffer, 2908 NULL, 2909 NULL, 2910 NULL); 2911 2912 return NO_ERROR; 2913 2914 case SO_ERROR: 2915 if (optlen < sizeof(INT)) 2916 { 2917 if (lpErrno) *lpErrno = WSAEFAULT; 2918 return SOCKET_ERROR; 2919 } 2920 2921 RtlCopyMemory(&Socket->SharedData->SocketLastError, 2922 optval, 2923 sizeof(INT)); 2924 return NO_ERROR; 2925 2926 case SO_SNDTIMEO: 2927 if (optlen < sizeof(DWORD)) 2928 { 2929 if (lpErrno) *lpErrno = WSAEFAULT; 2930 return SOCKET_ERROR; 2931 } 2932 2933 RtlCopyMemory(&Socket->SharedData->SendTimeout, 2934 optval, 2935 sizeof(DWORD)); 2936 return NO_ERROR; 2937 2938 case SO_RCVTIMEO: 2939 if (optlen < sizeof(DWORD)) 2940 { 2941 if (lpErrno) *lpErrno = WSAEFAULT; 2942 return SOCKET_ERROR; 2943 } 2944 2945 RtlCopyMemory(&Socket->SharedData->RecvTimeout, 2946 optval, 2947 sizeof(DWORD)); 2948 return NO_ERROR; 2949 2950 case SO_KEEPALIVE: 2951 case SO_DONTROUTE: 2952 /* These go directly to the helper dll */ 2953 goto SendToHelper; 2954 2955 default: 2956 /* Obviously this is a hack */ 2957 ERR("MSAFD: Set unknown optname %x\n", optname); 2958 return NO_ERROR; 2959 } 2960 } 2961 2962 SendToHelper: 2963 Errno = Socket->HelperData->WSHSetSocketInformation(Socket->HelperContext, 2964 s, 2965 Socket->TdiAddressHandle, 2966 Socket->TdiConnectionHandle, 2967 level, 2968 optname, 2969 (PCHAR)optval, 2970 optlen); 2971 if (lpErrno) *lpErrno = Errno; 2972 return (Errno == NO_ERROR) ? NO_ERROR : SOCKET_ERROR; 2973 } 2974 2975 /* 2976 * FUNCTION: Initialize service provider for a client 2977 * ARGUMENTS: 2978 * wVersionRequested = Highest WinSock SPI version that the caller can use 2979 * lpWSPData = Address of WSPDATA structure to initialize 2980 * lpProtocolInfo = Pointer to structure that defines the desired protocol 2981 * UpcallTable = Pointer to upcall table of the WinSock DLL 2982 * lpProcTable = Address of procedure table to initialize 2983 * RETURNS: 2984 * Status of operation 2985 */ 2986 _Must_inspect_result_ 2987 int 2988 WSPAPI 2989 WSPStartup( 2990 _In_ WORD wVersionRequested, 2991 _In_ LPWSPDATA lpWSPData, 2992 _In_ LPWSAPROTOCOL_INFOW lpProtocolInfo, 2993 _In_ WSPUPCALLTABLE UpcallTable, 2994 _Out_ LPWSPPROC_TABLE lpProcTable) 2995 { 2996 NTSTATUS Status; 2997 2998 if (((LOBYTE(wVersionRequested) == 2) && (HIBYTE(wVersionRequested) < 2)) || 2999 (LOBYTE(wVersionRequested) < 2)) 3000 { 3001 ERR("WSPStartup NOT SUPPORTED for version 0x%X\n", wVersionRequested); 3002 return WSAVERNOTSUPPORTED; 3003 } 3004 else 3005 Status = NO_ERROR; 3006 /* FIXME: Enable all cases of WSPStartup status */ 3007 Upcalls = UpcallTable; 3008 3009 if (Status == NO_ERROR) 3010 { 3011 lpProcTable->lpWSPAccept = WSPAccept; 3012 lpProcTable->lpWSPAddressToString = WSPAddressToString; 3013 lpProcTable->lpWSPAsyncSelect = WSPAsyncSelect; 3014 lpProcTable->lpWSPBind = WSPBind; 3015 lpProcTable->lpWSPCancelBlockingCall = WSPCancelBlockingCall; 3016 lpProcTable->lpWSPCleanup = WSPCleanup; 3017 lpProcTable->lpWSPCloseSocket = WSPCloseSocket; 3018 lpProcTable->lpWSPConnect = WSPConnect; 3019 lpProcTable->lpWSPDuplicateSocket = WSPDuplicateSocket; 3020 lpProcTable->lpWSPEnumNetworkEvents = WSPEnumNetworkEvents; 3021 lpProcTable->lpWSPEventSelect = WSPEventSelect; 3022 lpProcTable->lpWSPGetOverlappedResult = WSPGetOverlappedResult; 3023 lpProcTable->lpWSPGetPeerName = WSPGetPeerName; 3024 lpProcTable->lpWSPGetSockName = WSPGetSockName; 3025 lpProcTable->lpWSPGetSockOpt = WSPGetSockOpt; 3026 lpProcTable->lpWSPGetQOSByName = WSPGetQOSByName; 3027 lpProcTable->lpWSPIoctl = WSPIoctl; 3028 lpProcTable->lpWSPJoinLeaf = WSPJoinLeaf; 3029 lpProcTable->lpWSPListen = WSPListen; 3030 lpProcTable->lpWSPRecv = WSPRecv; 3031 lpProcTable->lpWSPRecvDisconnect = WSPRecvDisconnect; 3032 lpProcTable->lpWSPRecvFrom = WSPRecvFrom; 3033 lpProcTable->lpWSPSelect = WSPSelect; 3034 lpProcTable->lpWSPSend = WSPSend; 3035 lpProcTable->lpWSPSendDisconnect = WSPSendDisconnect; 3036 lpProcTable->lpWSPSendTo = WSPSendTo; 3037 lpProcTable->lpWSPSetSockOpt = WSPSetSockOpt; 3038 lpProcTable->lpWSPShutdown = WSPShutdown; 3039 lpProcTable->lpWSPSocket = WSPSocket; 3040 lpProcTable->lpWSPStringToAddress = WSPStringToAddress; 3041 lpWSPData->wVersion = MAKEWORD(2, 2); 3042 lpWSPData->wHighVersion = MAKEWORD(2, 2); 3043 /* Save CatalogEntryId for all upcalls */ 3044 CatalogEntryId = lpProtocolInfo->dwCatalogEntryId; 3045 } 3046 3047 TRACE("Status (%d).\n", Status); 3048 return Status; 3049 } 3050 3051 3052 INT 3053 WSPAPI 3054 WSPAddressToString(IN LPSOCKADDR lpsaAddress, 3055 IN DWORD dwAddressLength, 3056 IN LPWSAPROTOCOL_INFOW lpProtocolInfo, 3057 OUT LPWSTR lpszAddressString, 3058 IN OUT LPDWORD lpdwAddressStringLength, 3059 OUT LPINT lpErrno) 3060 { 3061 SIZE_T size; 3062 WCHAR buffer[54]; /* 32 digits + 7':' + '[' + '%" + 5 digits + ']:' + 5 digits + '\0' */ 3063 WCHAR *p; 3064 3065 if (!lpsaAddress || !lpszAddressString || !lpdwAddressStringLength) 3066 { 3067 if (lpErrno) *lpErrno = WSAEFAULT; 3068 return SOCKET_ERROR; 3069 } 3070 3071 switch (lpsaAddress->sa_family) 3072 { 3073 case AF_INET: 3074 if (dwAddressLength < sizeof(SOCKADDR_IN)) 3075 { 3076 if (lpErrno) *lpErrno = WSAEINVAL; 3077 return SOCKET_ERROR; 3078 } 3079 swprintf(buffer, 3080 L"%u.%u.%u.%u:%u", 3081 (unsigned int)(ntohl(((SOCKADDR_IN *)lpsaAddress)->sin_addr.s_addr) >> 24 & 0xff), 3082 (unsigned int)(ntohl(((SOCKADDR_IN *)lpsaAddress)->sin_addr.s_addr) >> 16 & 0xff), 3083 (unsigned int)(ntohl(((SOCKADDR_IN *)lpsaAddress)->sin_addr.s_addr) >> 8 & 0xff), 3084 (unsigned int)(ntohl(((SOCKADDR_IN *)lpsaAddress)->sin_addr.s_addr) & 0xff), 3085 ntohs(((SOCKADDR_IN *)lpsaAddress)->sin_port)); 3086 3087 p = wcschr(buffer, L':'); 3088 if (!((SOCKADDR_IN *)lpsaAddress)->sin_port) 3089 { 3090 *p = 0; 3091 } 3092 break; 3093 default: 3094 if (lpErrno) *lpErrno = WSAEINVAL; 3095 return SOCKET_ERROR; 3096 } 3097 3098 size = wcslen(buffer) + 1; 3099 3100 if (*lpdwAddressStringLength < size) 3101 { 3102 *lpdwAddressStringLength = size; 3103 if (lpErrno) *lpErrno = WSAEFAULT; 3104 return SOCKET_ERROR; 3105 } 3106 3107 *lpdwAddressStringLength = size; 3108 wcscpy(lpszAddressString, buffer); 3109 return 0; 3110 } 3111 3112 INT 3113 WSPAPI 3114 WSPStringToAddress(IN LPWSTR AddressString, 3115 IN INT AddressFamily, 3116 IN LPWSAPROTOCOL_INFOW lpProtocolInfo, 3117 OUT LPSOCKADDR lpAddress, 3118 IN OUT LPINT lpAddressLength, 3119 OUT LPINT lpErrno) 3120 { 3121 int numdots = 0; 3122 USHORT port; 3123 LONG inetaddr = 0, ip_part; 3124 LPWSTR *bp = NULL; 3125 SOCKADDR_IN *sockaddr; 3126 3127 if (!lpAddressLength || !lpAddress || !AddressString) 3128 { 3129 if (lpErrno) *lpErrno = WSAEINVAL; 3130 return SOCKET_ERROR; 3131 } 3132 3133 sockaddr = (SOCKADDR_IN *)lpAddress; 3134 3135 /* Set right address family */ 3136 if (lpProtocolInfo != NULL) 3137 { 3138 sockaddr->sin_family = lpProtocolInfo->iAddressFamily; 3139 } 3140 else 3141 { 3142 sockaddr->sin_family = AddressFamily; 3143 } 3144 3145 /* Report size */ 3146 if (AddressFamily == AF_INET) 3147 { 3148 if (*lpAddressLength < (INT)sizeof(SOCKADDR_IN)) 3149 { 3150 if (lpErrno) *lpErrno = WSAEFAULT; 3151 } 3152 else 3153 { 3154 // translate ip string to ip 3155 3156 /* Get ip number */ 3157 bp = &AddressString; 3158 inetaddr = 0; 3159 3160 while (*bp < &AddressString[wcslen(AddressString)]) 3161 { 3162 ip_part = wcstol(*bp, bp, 10); 3163 /* ip part number should be in range 0-255 */ 3164 if (ip_part < 0 || ip_part > 255) 3165 { 3166 if (lpErrno) *lpErrno = WSAEINVAL; 3167 return SOCKET_ERROR; 3168 } 3169 inetaddr = (inetaddr << 8) + ip_part; 3170 /* we end on string end or port separator */ 3171 if ((*bp)[0] == 0 || (*bp)[0] == L':') 3172 break; 3173 /* ip parts are dot separated. verify it */ 3174 if ((*bp)[0] != L'.') 3175 { 3176 if (lpErrno) *lpErrno = WSAEINVAL; 3177 return SOCKET_ERROR; 3178 } 3179 /* count the dots */ 3180 numdots++; 3181 /* move over the dot to next ip part */ 3182 (*bp)++; 3183 } 3184 3185 /* check dots count */ 3186 if (numdots != 3) 3187 { 3188 if (lpErrno) *lpErrno = WSAEINVAL; 3189 return SOCKET_ERROR; 3190 } 3191 3192 /* Get port number */ 3193 if ((*bp)[0] == L':') 3194 { 3195 /* move over the column to port part */ 3196 (*bp)++; 3197 /* next char should be numeric */ 3198 if ((*bp)[0] < L'0' || (*bp)[0] > L'9') 3199 { 3200 if (lpErrno) *lpErrno = WSAEINVAL; 3201 return SOCKET_ERROR; 3202 } 3203 port = wcstol(*bp, bp, 10); 3204 } 3205 else 3206 { 3207 port = 0; 3208 } 3209 3210 if (lpErrno) *lpErrno = NO_ERROR; 3211 /* rest sockaddr.sin_addr.s_addr 3212 for we need to be sure it is zero when we come to while */ 3213 *lpAddressLength = sizeof(*sockaddr); 3214 memset(lpAddress, 0, sizeof(*sockaddr)); 3215 sockaddr->sin_family = AF_INET; 3216 sockaddr->sin_addr.s_addr = inetaddr; 3217 sockaddr->sin_port = port; 3218 } 3219 } 3220 3221 if (lpErrno && !*lpErrno) 3222 { 3223 return 0; 3224 } 3225 3226 return SOCKET_ERROR; 3227 } 3228 3229 /* 3230 * FUNCTION: Cleans up service provider for a client 3231 * ARGUMENTS: 3232 * lpErrno = Address of buffer for error information 3233 * RETURNS: 3234 * 0 if successful, or SOCKET_ERROR if not 3235 */ 3236 INT 3237 WSPAPI 3238 WSPCleanup(OUT LPINT lpErrno) 3239 3240 { 3241 TRACE("Leaving.\n"); 3242 3243 if (lpErrno) *lpErrno = NO_ERROR; 3244 3245 return 0; 3246 } 3247 3248 VOID 3249 NTAPI 3250 AfdInfoAPC(PVOID ApcContext, 3251 PIO_STATUS_BLOCK IoStatusBlock, 3252 ULONG Reserved) 3253 { 3254 PAFDAPCCONTEXT Context = ApcContext; 3255 3256 Context->lpCompletionRoutine(IoStatusBlock->Status, IoStatusBlock->Information, Context->lpOverlapped, 0); 3257 HeapFree(GlobalHeap, 0, ApcContext); 3258 } 3259 3260 int 3261 GetSocketInformation(PSOCKET_INFORMATION Socket, 3262 ULONG AfdInformationClass, 3263 PBOOLEAN Boolean OPTIONAL, 3264 PULONG Ulong OPTIONAL, 3265 PLARGE_INTEGER LargeInteger OPTIONAL, 3266 LPWSAOVERLAPPED Overlapped OPTIONAL, 3267 LPWSAOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine OPTIONAL) 3268 { 3269 PIO_STATUS_BLOCK IOSB; 3270 IO_STATUS_BLOCK DummyIOSB; 3271 AFD_INFO InfoData; 3272 NTSTATUS Status; 3273 PAFDAPCCONTEXT APCContext; 3274 PIO_APC_ROUTINE APCFunction; 3275 HANDLE Event = NULL; 3276 HANDLE SockEvent; 3277 3278 Status = NtCreateEvent(&SockEvent, 3279 EVENT_ALL_ACCESS, 3280 NULL, 3281 SynchronizationEvent, 3282 FALSE); 3283 3284 if( !NT_SUCCESS(Status) ) 3285 return SOCKET_ERROR; 3286 3287 /* Set Info Class */ 3288 InfoData.InformationClass = AfdInformationClass; 3289 3290 /* Verify if we should use APC */ 3291 if (Overlapped == NULL) 3292 { 3293 /* Not using Overlapped structure, so use normal blocking on event */ 3294 APCContext = NULL; 3295 APCFunction = NULL; 3296 Event = SockEvent; 3297 IOSB = &DummyIOSB; 3298 } 3299 else 3300 { 3301 /* Overlapped request for non overlapped opened socket */ 3302 if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0) 3303 { 3304 TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n"); 3305 NtClose( SockEvent ); 3306 return 0; 3307 } 3308 if (CompletionRoutine == NULL) 3309 { 3310 /* Using Overlapped Structure, but no Completition Routine, so no need for APC */ 3311 APCContext = (PAFDAPCCONTEXT)Overlapped; 3312 APCFunction = NULL; 3313 Event = Overlapped->hEvent; 3314 } 3315 else 3316 { 3317 /* Using Overlapped Structure and a Completition Routine, so use an APC */ 3318 APCFunction = &AfdInfoAPC; // should be a private io completition function inside us 3319 APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT)); 3320 if (!APCContext) 3321 { 3322 ERR("Not enough memory for APC Context\n"); 3323 NtClose( SockEvent ); 3324 return WSAEFAULT; 3325 } 3326 APCContext->lpCompletionRoutine = CompletionRoutine; 3327 APCContext->lpOverlapped = Overlapped; 3328 APCContext->lpSocket = Socket; 3329 } 3330 3331 IOSB = (PIO_STATUS_BLOCK)&Overlapped->Internal; 3332 } 3333 3334 IOSB->Status = STATUS_PENDING; 3335 3336 /* Send IOCTL */ 3337 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle, 3338 Event, 3339 APCFunction, 3340 APCContext, 3341 IOSB, 3342 IOCTL_AFD_GET_INFO, 3343 &InfoData, 3344 sizeof(InfoData), 3345 &InfoData, 3346 sizeof(InfoData)); 3347 3348 /* Wait for return */ 3349 if (Status == STATUS_PENDING && Overlapped == NULL) 3350 { 3351 WaitForSingleObject(SockEvent, INFINITE); 3352 Status = IOSB->Status; 3353 } 3354 3355 NtClose( SockEvent ); 3356 3357 TRACE("Status %x Information %d\n", Status, IOSB->Information); 3358 3359 if (Status == STATUS_PENDING) 3360 { 3361 TRACE("Leaving (Pending)\n"); 3362 return WSA_IO_PENDING; 3363 } 3364 3365 if (Status != STATUS_SUCCESS) 3366 return SOCKET_ERROR; 3367 3368 /* Return Information */ 3369 if (Ulong != NULL) 3370 { 3371 *Ulong = InfoData.Information.Ulong; 3372 } 3373 if (LargeInteger != NULL) 3374 { 3375 *LargeInteger = InfoData.Information.LargeInteger; 3376 } 3377 if (Boolean != NULL) 3378 { 3379 *Boolean = InfoData.Information.Boolean; 3380 } 3381 3382 return NO_ERROR; 3383 3384 } 3385 3386 3387 int 3388 SetSocketInformation(PSOCKET_INFORMATION Socket, 3389 ULONG AfdInformationClass, 3390 PBOOLEAN Boolean OPTIONAL, 3391 PULONG Ulong OPTIONAL, 3392 PLARGE_INTEGER LargeInteger OPTIONAL, 3393 LPWSAOVERLAPPED Overlapped OPTIONAL, 3394 LPWSAOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine OPTIONAL) 3395 { 3396 PIO_STATUS_BLOCK IOSB; 3397 IO_STATUS_BLOCK DummyIOSB; 3398 AFD_INFO InfoData; 3399 NTSTATUS Status; 3400 PAFDAPCCONTEXT APCContext; 3401 PIO_APC_ROUTINE APCFunction; 3402 HANDLE Event = NULL; 3403 HANDLE SockEvent; 3404 3405 Status = NtCreateEvent(&SockEvent, 3406 EVENT_ALL_ACCESS, 3407 NULL, 3408 SynchronizationEvent, 3409 FALSE); 3410 3411 if( !NT_SUCCESS(Status) ) 3412 return SOCKET_ERROR; 3413 3414 /* Set Info Class */ 3415 InfoData.InformationClass = AfdInformationClass; 3416 3417 /* Set Information */ 3418 if (Ulong != NULL) 3419 { 3420 InfoData.Information.Ulong = *Ulong; 3421 } 3422 if (LargeInteger != NULL) 3423 { 3424 InfoData.Information.LargeInteger = *LargeInteger; 3425 } 3426 if (Boolean != NULL) 3427 { 3428 InfoData.Information.Boolean = *Boolean; 3429 } 3430 3431 /* Verify if we should use APC */ 3432 if (Overlapped == NULL) 3433 { 3434 /* Not using Overlapped structure, so use normal blocking on event */ 3435 APCContext = NULL; 3436 APCFunction = NULL; 3437 Event = SockEvent; 3438 IOSB = &DummyIOSB; 3439 } 3440 else 3441 { 3442 /* Overlapped request for non overlapped opened socket */ 3443 if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0) 3444 { 3445 TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n"); 3446 NtClose( SockEvent ); 3447 return 0; 3448 } 3449 if (CompletionRoutine == NULL) 3450 { 3451 /* Using Overlapped Structure, but no Completition Routine, so no need for APC */ 3452 APCContext = (PAFDAPCCONTEXT)Overlapped; 3453 APCFunction = NULL; 3454 Event = Overlapped->hEvent; 3455 } 3456 else 3457 { 3458 /* Using Overlapped Structure and a Completition Routine, so use an APC */ 3459 APCFunction = &AfdInfoAPC; // should be a private io completition function inside us 3460 APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT)); 3461 if (!APCContext) 3462 { 3463 ERR("Not enough memory for APC Context\n"); 3464 NtClose( SockEvent ); 3465 return WSAEFAULT; 3466 } 3467 APCContext->lpCompletionRoutine = CompletionRoutine; 3468 APCContext->lpOverlapped = Overlapped; 3469 APCContext->lpSocket = Socket; 3470 } 3471 3472 IOSB = (PIO_STATUS_BLOCK)&Overlapped->Internal; 3473 } 3474 3475 IOSB->Status = STATUS_PENDING; 3476 3477 /* Send IOCTL */ 3478 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle, 3479 Event, 3480 APCFunction, 3481 APCContext, 3482 IOSB, 3483 IOCTL_AFD_SET_INFO, 3484 &InfoData, 3485 sizeof(InfoData), 3486 NULL, 3487 0); 3488 3489 /* Wait for return */ 3490 if (Status == STATUS_PENDING && Overlapped == NULL) 3491 { 3492 WaitForSingleObject(SockEvent, INFINITE); 3493 Status = IOSB->Status; 3494 } 3495 3496 NtClose( SockEvent ); 3497 3498 TRACE("Status %x Information %d\n", Status, IOSB->Information); 3499 3500 if (Status == STATUS_PENDING) 3501 { 3502 TRACE("Leaving (Pending)\n"); 3503 return WSA_IO_PENDING; 3504 } 3505 3506 return Status == STATUS_SUCCESS ? NO_ERROR : SOCKET_ERROR; 3507 3508 } 3509 3510 PSOCKET_INFORMATION 3511 GetSocketStructure(SOCKET Handle) 3512 { 3513 PSOCKET_INFORMATION CurrentSocket; 3514 3515 EnterCriticalSection(&SocketListLock); 3516 3517 CurrentSocket = SocketListHead; 3518 while (CurrentSocket) 3519 { 3520 if (CurrentSocket->Handle == Handle) 3521 { 3522 LeaveCriticalSection(&SocketListLock); 3523 return CurrentSocket; 3524 } 3525 3526 CurrentSocket = CurrentSocket->NextSocket; 3527 } 3528 3529 LeaveCriticalSection(&SocketListLock); 3530 3531 return NULL; 3532 } 3533 3534 int CreateContext(PSOCKET_INFORMATION Socket) 3535 { 3536 IO_STATUS_BLOCK IOSB; 3537 SOCKET_CONTEXT ContextData; 3538 NTSTATUS Status; 3539 HANDLE SockEvent; 3540 3541 Status = NtCreateEvent(&SockEvent, 3542 EVENT_ALL_ACCESS, 3543 NULL, 3544 SynchronizationEvent, 3545 FALSE); 3546 3547 if( !NT_SUCCESS(Status) ) 3548 return SOCKET_ERROR; 3549 3550 /* Create Context */ 3551 ContextData.SharedData = *Socket->SharedData; 3552 ContextData.SizeOfHelperData = 0; 3553 RtlCopyMemory (&ContextData.LocalAddress, 3554 Socket->LocalAddress, 3555 Socket->SharedData->SizeOfLocalAddress); 3556 RtlCopyMemory (&ContextData.RemoteAddress, 3557 Socket->RemoteAddress, 3558 Socket->SharedData->SizeOfRemoteAddress); 3559 3560 /* Send IOCTL */ 3561 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle, 3562 SockEvent, 3563 NULL, 3564 NULL, 3565 &IOSB, 3566 IOCTL_AFD_SET_CONTEXT, 3567 &ContextData, 3568 sizeof(ContextData), 3569 NULL, 3570 0); 3571 3572 /* Wait for Completion */ 3573 if (Status == STATUS_PENDING) 3574 { 3575 WaitForSingleObject(SockEvent, INFINITE); 3576 Status = IOSB.Status; 3577 } 3578 3579 NtClose( SockEvent ); 3580 3581 return Status == STATUS_SUCCESS ? NO_ERROR : SOCKET_ERROR; 3582 } 3583 3584 BOOLEAN SockCreateOrReferenceAsyncThread(VOID) 3585 { 3586 HANDLE hAsyncThread; 3587 DWORD AsyncThreadId; 3588 HANDLE AsyncEvent; 3589 OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags; 3590 NTSTATUS Status; 3591 3592 /* Check if the Thread Already Exists */ 3593 if (SockAsyncThreadRefCount) 3594 { 3595 ASSERT(SockAsyncCompletionPort); 3596 return TRUE; 3597 } 3598 3599 /* Create the Completion Port */ 3600 if (!SockAsyncCompletionPort) 3601 { 3602 Status = NtCreateIoCompletion(&SockAsyncCompletionPort, 3603 IO_COMPLETION_ALL_ACCESS, 3604 NULL, 3605 2); // Allow 2 threads only 3606 if (!NT_SUCCESS(Status)) 3607 { 3608 ERR("Failed to create completion port: 0x%08x\n", Status); 3609 return FALSE; 3610 } 3611 /* Protect Handle */ 3612 HandleFlags.ProtectFromClose = TRUE; 3613 HandleFlags.Inherit = FALSE; 3614 Status = NtSetInformationObject(SockAsyncCompletionPort, 3615 ObjectHandleFlagInformation, 3616 &HandleFlags, 3617 sizeof(HandleFlags)); 3618 } 3619 3620 /* Create the Async Event */ 3621 Status = NtCreateEvent(&AsyncEvent, 3622 EVENT_ALL_ACCESS, 3623 NULL, 3624 NotificationEvent, 3625 FALSE); 3626 3627 /* Create the Async Thread */ 3628 hAsyncThread = CreateThread(NULL, 3629 0, 3630 SockAsyncThread, 3631 NULL, 3632 0, 3633 &AsyncThreadId); 3634 3635 /* Close the Handle */ 3636 NtClose(hAsyncThread); 3637 3638 /* Increase the Reference Count */ 3639 SockAsyncThreadRefCount++; 3640 return TRUE; 3641 } 3642 3643 ULONG 3644 NTAPI 3645 SockAsyncThread(PVOID ThreadParam) 3646 { 3647 PVOID AsyncContext; 3648 PASYNC_COMPLETION_ROUTINE AsyncCompletionRoutine; 3649 IO_STATUS_BLOCK IOSB; 3650 NTSTATUS Status; 3651 3652 /* Make the Thread Higher Priority */ 3653 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); 3654 3655 /* Do a KQUEUE/WorkItem Style Loop, thanks to IoCompletion Ports */ 3656 do 3657 { 3658 Status = NtRemoveIoCompletion (SockAsyncCompletionPort, 3659 (PVOID*)&AsyncCompletionRoutine, 3660 &AsyncContext, 3661 &IOSB, 3662 NULL); 3663 /* Call the Async Function */ 3664 if (NT_SUCCESS(Status)) 3665 { 3666 (*AsyncCompletionRoutine)(AsyncContext, &IOSB); 3667 } 3668 else 3669 { 3670 /* It Failed, sleep for a second */ 3671 Sleep(1000); 3672 } 3673 } while ((Status != STATUS_TIMEOUT)); 3674 3675 /* The Thread has Ended */ 3676 return 0; 3677 } 3678 3679 BOOLEAN SockGetAsyncSelectHelperAfdHandle(VOID) 3680 { 3681 UNICODE_STRING AfdHelper; 3682 OBJECT_ATTRIBUTES ObjectAttributes; 3683 IO_STATUS_BLOCK IoSb; 3684 FILE_COMPLETION_INFORMATION CompletionInfo; 3685 OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags; 3686 3687 /* First, make sure we're not already initialized */ 3688 if (SockAsyncHelperAfdHandle) 3689 { 3690 return TRUE; 3691 } 3692 3693 /* Set up Handle Name and Object */ 3694 RtlInitUnicodeString(&AfdHelper, L"\\Device\\Afd\\AsyncSelectHlp" ); 3695 InitializeObjectAttributes(&ObjectAttributes, 3696 &AfdHelper, 3697 OBJ_INHERIT | OBJ_CASE_INSENSITIVE, 3698 NULL, 3699 NULL); 3700 3701 /* Open the Handle to AFD */ 3702 NtCreateFile(&SockAsyncHelperAfdHandle, 3703 GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 3704 &ObjectAttributes, 3705 &IoSb, 3706 NULL, 3707 0, 3708 FILE_SHARE_READ | FILE_SHARE_WRITE, 3709 FILE_OPEN_IF, 3710 0, 3711 NULL, 3712 0); 3713 3714 /* 3715 * Now Set up the Completion Port Information 3716 * This means that whenever a Poll is finished, the routine will be executed 3717 */ 3718 CompletionInfo.Port = SockAsyncCompletionPort; 3719 CompletionInfo.Key = SockAsyncSelectCompletionRoutine; 3720 NtSetInformationFile(SockAsyncHelperAfdHandle, 3721 &IoSb, 3722 &CompletionInfo, 3723 sizeof(CompletionInfo), 3724 FileCompletionInformation); 3725 3726 3727 /* Protect the Handle */ 3728 HandleFlags.ProtectFromClose = TRUE; 3729 HandleFlags.Inherit = FALSE; 3730 NtSetInformationObject(SockAsyncCompletionPort, 3731 ObjectHandleFlagInformation, 3732 &HandleFlags, 3733 sizeof(HandleFlags)); 3734 3735 3736 /* Set this variable to true so that Send/Recv/Accept will know wether to renable disabled events */ 3737 SockAsyncSelectCalled = TRUE; 3738 return TRUE; 3739 } 3740 3741 VOID SockAsyncSelectCompletionRoutine(PVOID Context, PIO_STATUS_BLOCK IoStatusBlock) 3742 { 3743 3744 PASYNC_DATA AsyncData = Context; 3745 PSOCKET_INFORMATION Socket; 3746 ULONG x; 3747 3748 /* Get the Socket */ 3749 Socket = AsyncData->ParentSocket; 3750 3751 /* Check if the Sequence Number Changed behind our back */ 3752 if (AsyncData->SequenceNumber != Socket->SharedData->SequenceNumber ) 3753 { 3754 return; 3755 } 3756 3757 /* Check we were manually called b/c of a failure */ 3758 if (!NT_SUCCESS(IoStatusBlock->Status)) 3759 { 3760 /* FIXME: Perform Upcall */ 3761 return; 3762 } 3763 3764 for (x = 1; x; x<<=1) 3765 { 3766 switch (AsyncData->AsyncSelectInfo.Handles[0].Events & x) 3767 { 3768 case AFD_EVENT_RECEIVE: 3769 if (0 != (Socket->SharedData->AsyncEvents & FD_READ) && 3770 0 == (Socket->SharedData->AsyncDisabledEvents & FD_READ)) 3771 { 3772 /* Make the Notification */ 3773 (Upcalls.lpWPUPostMessage)(Socket->SharedData->hWnd, 3774 Socket->SharedData->wMsg, 3775 Socket->Handle, 3776 WSAMAKESELECTREPLY(FD_READ, 0)); 3777 /* Disable this event until the next read(); */ 3778 Socket->SharedData->AsyncDisabledEvents |= FD_READ; 3779 } 3780 break; 3781 3782 case AFD_EVENT_OOB_RECEIVE: 3783 if (0 != (Socket->SharedData->AsyncEvents & FD_OOB) && 3784 0 == (Socket->SharedData->AsyncDisabledEvents & FD_OOB)) 3785 { 3786 /* Make the Notification */ 3787 (Upcalls.lpWPUPostMessage)(Socket->SharedData->hWnd, 3788 Socket->SharedData->wMsg, 3789 Socket->Handle, 3790 WSAMAKESELECTREPLY(FD_OOB, 0)); 3791 /* Disable this event until the next read(); */ 3792 Socket->SharedData->AsyncDisabledEvents |= FD_OOB; 3793 } 3794 break; 3795 3796 case AFD_EVENT_SEND: 3797 if (0 != (Socket->SharedData->AsyncEvents & FD_WRITE) && 3798 0 == (Socket->SharedData->AsyncDisabledEvents & FD_WRITE)) 3799 { 3800 /* Make the Notification */ 3801 (Upcalls.lpWPUPostMessage)(Socket->SharedData->hWnd, 3802 Socket->SharedData->wMsg, 3803 Socket->Handle, 3804 WSAMAKESELECTREPLY(FD_WRITE, 0)); 3805 /* Disable this event until the next write(); */ 3806 Socket->SharedData->AsyncDisabledEvents |= FD_WRITE; 3807 } 3808 break; 3809 3810 /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */ 3811 case AFD_EVENT_CONNECT: 3812 case AFD_EVENT_CONNECT_FAIL: 3813 if (0 != (Socket->SharedData->AsyncEvents & FD_CONNECT) && 3814 0 == (Socket->SharedData->AsyncDisabledEvents & FD_CONNECT)) 3815 { 3816 /* Make the Notification */ 3817 (Upcalls.lpWPUPostMessage)(Socket->SharedData->hWnd, 3818 Socket->SharedData->wMsg, 3819 Socket->Handle, 3820 WSAMAKESELECTREPLY(FD_CONNECT, 0)); 3821 /* Disable this event forever; */ 3822 Socket->SharedData->AsyncDisabledEvents |= FD_CONNECT; 3823 } 3824 break; 3825 3826 case AFD_EVENT_ACCEPT: 3827 if (0 != (Socket->SharedData->AsyncEvents & FD_ACCEPT) && 3828 0 == (Socket->SharedData->AsyncDisabledEvents & FD_ACCEPT)) 3829 { 3830 /* Make the Notification */ 3831 (Upcalls.lpWPUPostMessage)(Socket->SharedData->hWnd, 3832 Socket->SharedData->wMsg, 3833 Socket->Handle, 3834 WSAMAKESELECTREPLY(FD_ACCEPT, 0)); 3835 /* Disable this event until the next accept(); */ 3836 Socket->SharedData->AsyncDisabledEvents |= FD_ACCEPT; 3837 } 3838 break; 3839 3840 case AFD_EVENT_DISCONNECT: 3841 case AFD_EVENT_ABORT: 3842 case AFD_EVENT_CLOSE: 3843 if (0 != (Socket->SharedData->AsyncEvents & FD_CLOSE) && 3844 0 == (Socket->SharedData->AsyncDisabledEvents & FD_CLOSE)) 3845 { 3846 /* Make the Notification */ 3847 (Upcalls.lpWPUPostMessage)(Socket->SharedData->hWnd, 3848 Socket->SharedData->wMsg, 3849 Socket->Handle, 3850 WSAMAKESELECTREPLY(FD_CLOSE, 0)); 3851 /* Disable this event forever; */ 3852 Socket->SharedData->AsyncDisabledEvents |= FD_CLOSE; 3853 } 3854 break; 3855 /* FIXME: Support QOS */ 3856 } 3857 } 3858 3859 /* Check if there are any events left for us to check */ 3860 if ((Socket->SharedData->AsyncEvents & (~Socket->SharedData->AsyncDisabledEvents)) == 0 ) 3861 { 3862 return; 3863 } 3864 3865 /* Keep Polling */ 3866 SockProcessAsyncSelect(Socket, AsyncData); 3867 return; 3868 } 3869 3870 VOID SockProcessAsyncSelect(PSOCKET_INFORMATION Socket, PASYNC_DATA AsyncData) 3871 { 3872 3873 ULONG lNetworkEvents; 3874 NTSTATUS Status; 3875 3876 /* Set up the Async Data Event Info */ 3877 AsyncData->AsyncSelectInfo.Timeout.HighPart = 0x7FFFFFFF; 3878 AsyncData->AsyncSelectInfo.Timeout.LowPart = 0xFFFFFFFF; 3879 AsyncData->AsyncSelectInfo.HandleCount = 1; 3880 AsyncData->AsyncSelectInfo.Exclusive = TRUE; 3881 AsyncData->AsyncSelectInfo.Handles[0].Handle = Socket->Handle; 3882 AsyncData->AsyncSelectInfo.Handles[0].Events = 0; 3883 3884 /* Remove unwanted events */ 3885 lNetworkEvents = Socket->SharedData->AsyncEvents & (~Socket->SharedData->AsyncDisabledEvents); 3886 3887 /* Set Events to wait for */ 3888 if (lNetworkEvents & FD_READ) 3889 { 3890 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_RECEIVE; 3891 } 3892 3893 if (lNetworkEvents & FD_WRITE) 3894 { 3895 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_SEND; 3896 } 3897 3898 if (lNetworkEvents & FD_OOB) 3899 { 3900 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_OOB_RECEIVE; 3901 } 3902 3903 if (lNetworkEvents & FD_ACCEPT) 3904 { 3905 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_ACCEPT; 3906 } 3907 3908 /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */ 3909 if (lNetworkEvents & FD_CONNECT) 3910 { 3911 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_CONNECT | AFD_EVENT_CONNECT_FAIL; 3912 } 3913 3914 if (lNetworkEvents & FD_CLOSE) 3915 { 3916 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_DISCONNECT | AFD_EVENT_ABORT | AFD_EVENT_CLOSE; 3917 } 3918 3919 if (lNetworkEvents & FD_QOS) 3920 { 3921 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_QOS; 3922 } 3923 3924 if (lNetworkEvents & FD_GROUP_QOS) 3925 { 3926 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_GROUP_QOS; 3927 } 3928 3929 /* Send IOCTL */ 3930 Status = NtDeviceIoControlFile (SockAsyncHelperAfdHandle, 3931 NULL, 3932 NULL, 3933 AsyncData, 3934 &AsyncData->IoStatusBlock, 3935 IOCTL_AFD_SELECT, 3936 &AsyncData->AsyncSelectInfo, 3937 sizeof(AsyncData->AsyncSelectInfo), 3938 &AsyncData->AsyncSelectInfo, 3939 sizeof(AsyncData->AsyncSelectInfo)); 3940 3941 /* I/O Manager Won't call the completion routine, let's do it manually */ 3942 if (NT_SUCCESS(Status)) 3943 { 3944 return; 3945 } 3946 else 3947 { 3948 AsyncData->IoStatusBlock.Status = Status; 3949 SockAsyncSelectCompletionRoutine(AsyncData, &AsyncData->IoStatusBlock); 3950 } 3951 } 3952 3953 VOID SockProcessQueuedAsyncSelect(PVOID Context, PIO_STATUS_BLOCK IoStatusBlock) 3954 { 3955 PASYNC_DATA AsyncData = Context; 3956 BOOL FreeContext = TRUE; 3957 PSOCKET_INFORMATION Socket; 3958 3959 /* Get the Socket */ 3960 Socket = AsyncData->ParentSocket; 3961 3962 /* If someone closed it, stop the function */ 3963 if (Socket->SharedData->State != SocketClosed) 3964 { 3965 /* Check if the Sequence Number changed by now, in which case quit */ 3966 if (AsyncData->SequenceNumber == Socket->SharedData->SequenceNumber) 3967 { 3968 /* Do the actual select, if needed */ 3969 if ((Socket->SharedData->AsyncEvents & (~Socket->SharedData->AsyncDisabledEvents))) 3970 { 3971 SockProcessAsyncSelect(Socket, AsyncData); 3972 FreeContext = FALSE; 3973 } 3974 } 3975 } 3976 3977 /* Free the Context */ 3978 if (FreeContext) 3979 { 3980 HeapFree(GetProcessHeap(), 0, AsyncData); 3981 } 3982 3983 return; 3984 } 3985 3986 VOID 3987 SockReenableAsyncSelectEvent (IN PSOCKET_INFORMATION Socket, 3988 IN ULONG Event) 3989 { 3990 PASYNC_DATA AsyncData; 3991 3992 /* Make sure the event is actually disabled */ 3993 if (!(Socket->SharedData->AsyncDisabledEvents & Event)) 3994 { 3995 return; 3996 } 3997 3998 /* Re-enable it */ 3999 Socket->SharedData->AsyncDisabledEvents &= ~Event; 4000 4001 /* Return if no more events are being polled */ 4002 if ((Socket->SharedData->AsyncEvents & (~Socket->SharedData->AsyncDisabledEvents)) == 0 ) 4003 { 4004 return; 4005 } 4006 4007 /* Wait on new events */ 4008 AsyncData = HeapAlloc(GetProcessHeap(), 0, sizeof(ASYNC_DATA)); 4009 if (!AsyncData) return; 4010 4011 /* Create the Asynch Thread if Needed */ 4012 SockCreateOrReferenceAsyncThread(); 4013 4014 /* Increase the sequence number to stop anything else */ 4015 Socket->SharedData->SequenceNumber++; 4016 4017 /* Set up the Async Data */ 4018 AsyncData->ParentSocket = Socket; 4019 AsyncData->SequenceNumber = Socket->SharedData->SequenceNumber; 4020 4021 /* Begin Async Select by using I/O Completion */ 4022 NtSetIoCompletion(SockAsyncCompletionPort, 4023 (PVOID)&SockProcessQueuedAsyncSelect, 4024 AsyncData, 4025 0, 4026 0); 4027 4028 /* All done */ 4029 return; 4030 } 4031 4032 BOOL 4033 WINAPI 4034 DllMain(HANDLE hInstDll, 4035 ULONG dwReason, 4036 PVOID Reserved) 4037 { 4038 4039 switch (dwReason) 4040 { 4041 case DLL_PROCESS_ATTACH: 4042 4043 TRACE("Loading MSAFD.DLL \n"); 4044 4045 /* Don't need thread attach notifications 4046 so disable them to improve performance */ 4047 DisableThreadLibraryCalls(hInstDll); 4048 4049 /* List of DLL Helpers */ 4050 InitializeListHead(&SockHelpersListHead); 4051 4052 /* Heap to use when allocating */ 4053 GlobalHeap = GetProcessHeap(); 4054 4055 /* Initialize the lock that protects our socket list */ 4056 InitializeCriticalSection(&SocketListLock); 4057 4058 TRACE("MSAFD.DLL has been loaded\n"); 4059 4060 break; 4061 4062 case DLL_THREAD_ATTACH: 4063 break; 4064 4065 case DLL_THREAD_DETACH: 4066 break; 4067 4068 case DLL_PROCESS_DETACH: 4069 4070 /* Delete the socket list lock */ 4071 DeleteCriticalSection(&SocketListLock); 4072 4073 break; 4074 } 4075 4076 TRACE("DllMain of msafd.dll (leaving)\n"); 4077 4078 return TRUE; 4079 } 4080 4081 /* EOF */ 4082