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