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