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