PageRenderTime 4ms CodeModel.GetById 4ms app.highlight 63ms RepoModel.GetById 20ms app.codeStats 1ms

/dll/win32/msafd/misc/dllmain.c

https://bitbucket.org/arty/arty-newcc-reactos
C | 3025 lines | 2301 code | 424 blank | 300 comment | 367 complexity | 0e9108fd373225420c56433e6347f8f6 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/*
   2 * COPYRIGHT:   See COPYING in the top level directory
   3 * PROJECT:     ReactOS Ancillary Function Driver DLL
   4 * FILE:        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#if DBG
  16//DWORD DebugTraceLevel = DEBUG_ULTRA;
  17DWORD DebugTraceLevel = 0;
  18#endif /* DBG */
  19
  20HANDLE GlobalHeap;
  21WSPUPCALLTABLE Upcalls;
  22LPWPUCOMPLETEOVERLAPPEDREQUEST lpWPUCompleteOverlappedRequest;
  23PSOCKET_INFORMATION SocketListHead = NULL;
  24CRITICAL_SECTION SocketListLock;
  25LIST_ENTRY SockHelpersListHead = { NULL, NULL };
  26ULONG SockAsyncThreadRefCount;
  27HANDLE SockAsyncHelperAfdHandle;
  28HANDLE SockAsyncCompletionPort = NULL;
  29BOOLEAN SockAsyncSelectCalled;
  30
  31
  32
  33/*
  34 * FUNCTION: Creates a new socket
  35 * ARGUMENTS:
  36 *     af             = Address family
  37 *     type           = Socket type
  38 *     protocol       = Protocol type
  39 *     lpProtocolInfo = Pointer to protocol information
  40 *     g              = Reserved
  41 *     dwFlags        = Socket flags
  42 *     lpErrno        = Address of buffer for error information
  43 * RETURNS:
  44 *     Created socket, or INVALID_SOCKET if it could not be created
  45 */
  46SOCKET
  47WSPAPI
  48WSPSocket(int AddressFamily,
  49          int SocketType,
  50          int Protocol,
  51          LPWSAPROTOCOL_INFOW lpProtocolInfo,
  52          GROUP g,
  53          DWORD dwFlags,
  54          LPINT lpErrno)
  55{
  56    OBJECT_ATTRIBUTES           Object;
  57    IO_STATUS_BLOCK             IOSB;
  58    USHORT                      SizeOfPacket;
  59    ULONG                       SizeOfEA;
  60    PAFD_CREATE_PACKET          AfdPacket;
  61    HANDLE                      Sock;
  62    PSOCKET_INFORMATION         Socket = NULL;
  63    PFILE_FULL_EA_INFORMATION   EABuffer = NULL;
  64    PHELPER_DATA                HelperData;
  65    PVOID                       HelperDLLContext;
  66    DWORD                       HelperEvents;
  67    UNICODE_STRING              TransportName;
  68    UNICODE_STRING              DevName;
  69    LARGE_INTEGER               GroupData;
  70    INT                         Status;
  71
  72    AFD_DbgPrint(MAX_TRACE, ("Creating Socket, getting TDI Name\n"));
  73    AFD_DbgPrint(MAX_TRACE, ("AddressFamily (%d)  SocketType (%d)  Protocol (%d).\n",
  74                             AddressFamily, SocketType, Protocol));
  75
  76    /* Get Helper Data and Transport */
  77    Status = SockGetTdiName (&AddressFamily,
  78                             &SocketType,
  79                             &Protocol,
  80                             g,
  81                             dwFlags,
  82                             &TransportName,
  83                             &HelperDLLContext,
  84                             &HelperData,
  85                             &HelperEvents);
  86
  87    /* Check for error */
  88    if (Status != NO_ERROR)
  89    {
  90        AFD_DbgPrint(MID_TRACE,("SockGetTdiName: Status %x\n", Status));
  91        goto error;
  92    }
  93
  94    /* AFD Device Name */
  95    RtlInitUnicodeString(&DevName, L"\\Device\\Afd\\Endpoint");
  96
  97    /* Set Socket Data */
  98    Socket = HeapAlloc(GlobalHeap, 0, sizeof(*Socket));
  99    if (!Socket)
 100        return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL);
 101
 102    RtlZeroMemory(Socket, sizeof(*Socket));
 103    Socket->RefCount = 2;
 104    Socket->Handle = -1;
 105    Socket->SharedData.Listening = FALSE;
 106    Socket->SharedData.State = SocketOpen;
 107    Socket->SharedData.AddressFamily = AddressFamily;
 108    Socket->SharedData.SocketType = SocketType;
 109    Socket->SharedData.Protocol = Protocol;
 110    Socket->HelperContext = HelperDLLContext;
 111    Socket->HelperData = HelperData;
 112    Socket->HelperEvents = HelperEvents;
 113    Socket->LocalAddress = &Socket->WSLocalAddress;
 114    Socket->SharedData.SizeOfLocalAddress = HelperData->MaxWSAddressLength;
 115    Socket->RemoteAddress = &Socket->WSRemoteAddress;
 116    Socket->SharedData.SizeOfRemoteAddress = HelperData->MaxWSAddressLength;
 117    Socket->SharedData.UseDelayedAcceptance = HelperData->UseDelayedAcceptance;
 118    Socket->SharedData.CreateFlags = dwFlags;
 119    Socket->SharedData.CatalogEntryId = lpProtocolInfo->dwCatalogEntryId;
 120    Socket->SharedData.ServiceFlags1 = lpProtocolInfo->dwServiceFlags1;
 121    Socket->SharedData.ProviderFlags = lpProtocolInfo->dwProviderFlags;
 122    Socket->SharedData.GroupID = g;
 123    Socket->SharedData.GroupType = 0;
 124    Socket->SharedData.UseSAN = FALSE;
 125    Socket->SharedData.NonBlocking = FALSE; /* Sockets start blocking */
 126    Socket->SanData = NULL;
 127
 128    /* Ask alex about this */
 129    if( Socket->SharedData.SocketType == SOCK_DGRAM ||
 130        Socket->SharedData.SocketType == SOCK_RAW )
 131    {
 132        AFD_DbgPrint(MID_TRACE,("Connectionless socket\n"));
 133        Socket->SharedData.ServiceFlags1 |= XP1_CONNECTIONLESS;
 134    }
 135
 136    /* Packet Size */
 137    SizeOfPacket = TransportName.Length + sizeof(AFD_CREATE_PACKET) + sizeof(WCHAR);
 138
 139    /* EA Size */
 140    SizeOfEA = SizeOfPacket + sizeof(FILE_FULL_EA_INFORMATION) + AFD_PACKET_COMMAND_LENGTH;
 141
 142    /* Set up EA Buffer */
 143    EABuffer = HeapAlloc(GlobalHeap, 0, SizeOfEA);
 144    if (!EABuffer)
 145        return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL);
 146
 147    RtlZeroMemory(EABuffer, SizeOfEA);
 148    EABuffer->NextEntryOffset = 0;
 149    EABuffer->Flags = 0;
 150    EABuffer->EaNameLength = AFD_PACKET_COMMAND_LENGTH;
 151    RtlCopyMemory (EABuffer->EaName,
 152                   AfdCommand,
 153                   AFD_PACKET_COMMAND_LENGTH + 1);
 154    EABuffer->EaValueLength = SizeOfPacket;
 155
 156    /* Set up AFD Packet */
 157    AfdPacket = (PAFD_CREATE_PACKET)(EABuffer->EaName + EABuffer->EaNameLength + 1);
 158    AfdPacket->SizeOfTransportName = TransportName.Length;
 159    RtlCopyMemory (AfdPacket->TransportName,
 160                   TransportName.Buffer,
 161                   TransportName.Length + sizeof(WCHAR));
 162    AfdPacket->GroupID = g;
 163
 164    /* Set up Endpoint Flags */
 165    if ((Socket->SharedData.ServiceFlags1 & XP1_CONNECTIONLESS) != 0)
 166    {
 167        if ((SocketType != SOCK_DGRAM) && (SocketType != SOCK_RAW))
 168        {
 169            /* Only RAW or UDP can be Connectionless */
 170            goto error;
 171        }
 172        AfdPacket->EndpointFlags |= AFD_ENDPOINT_CONNECTIONLESS;
 173    }
 174
 175    if ((Socket->SharedData.ServiceFlags1 & XP1_MESSAGE_ORIENTED) != 0)
 176    {
 177        if (SocketType == SOCK_STREAM)
 178        {
 179            if ((Socket->SharedData.ServiceFlags1 & XP1_PSEUDO_STREAM) == 0)
 180            {
 181                /* The Provider doesn't actually support Message Oriented Streams */
 182                goto error;
 183            }
 184        }
 185        AfdPacket->EndpointFlags |= AFD_ENDPOINT_MESSAGE_ORIENTED;
 186    }
 187
 188    if (SocketType == SOCK_RAW) AfdPacket->EndpointFlags |= AFD_ENDPOINT_RAW;
 189
 190    if (dwFlags & (WSA_FLAG_MULTIPOINT_C_ROOT |
 191                   WSA_FLAG_MULTIPOINT_C_LEAF |
 192                   WSA_FLAG_MULTIPOINT_D_ROOT |
 193                   WSA_FLAG_MULTIPOINT_D_LEAF))
 194    {
 195        if ((Socket->SharedData.ServiceFlags1 & XP1_SUPPORT_MULTIPOINT) == 0)
 196        {
 197            /* The Provider doesn't actually support Multipoint */
 198            goto error;
 199        }
 200        AfdPacket->EndpointFlags |= AFD_ENDPOINT_MULTIPOINT;
 201
 202        if (dwFlags & WSA_FLAG_MULTIPOINT_C_ROOT)
 203        {
 204            if (((Socket->SharedData.ServiceFlags1 & XP1_MULTIPOINT_CONTROL_PLANE) == 0)
 205                || ((dwFlags & WSA_FLAG_MULTIPOINT_C_LEAF) != 0))
 206            {
 207                /* The Provider doesn't support Control Planes, or you already gave a leaf */
 208                goto error;
 209            }
 210            AfdPacket->EndpointFlags |= AFD_ENDPOINT_C_ROOT;
 211        }
 212
 213        if (dwFlags & WSA_FLAG_MULTIPOINT_D_ROOT)
 214        {
 215            if (((Socket->SharedData.ServiceFlags1 & XP1_MULTIPOINT_DATA_PLANE) == 0)
 216                || ((dwFlags & WSA_FLAG_MULTIPOINT_D_LEAF) != 0))
 217            {
 218                /* The Provider doesn't support Data Planes, or you already gave a leaf */
 219                goto error;
 220            }
 221            AfdPacket->EndpointFlags |= AFD_ENDPOINT_D_ROOT;
 222        }
 223    }
 224
 225    /* Set up Object Attributes */
 226    InitializeObjectAttributes (&Object,
 227                                &DevName,
 228                                OBJ_CASE_INSENSITIVE | OBJ_INHERIT,
 229                                0,
 230                                0);
 231
 232    /* Create the Socket as asynchronous. That means we have to block
 233    ourselves after every call to NtDeviceIoControlFile. This is
 234    because the kernel doesn't support overlapping synchronous I/O
 235    requests (made from multiple threads) at this time (Sep 2005) */
 236    Status = NtCreateFile(&Sock,
 237                          GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
 238                          &Object,
 239                          &IOSB,
 240                          NULL,
 241                          0,
 242                          FILE_SHARE_READ | FILE_SHARE_WRITE,
 243                          FILE_OPEN_IF,
 244                          0,
 245                          EABuffer,
 246                          SizeOfEA);
 247
 248    HeapFree(GlobalHeap, 0, EABuffer);
 249
 250    if (Status != STATUS_SUCCESS)
 251    {
 252        AFD_DbgPrint(MIN_TRACE, ("Failed to open socket\n"));
 253
 254        HeapFree(GlobalHeap, 0, Socket);
 255
 256        return MsafdReturnWithErrno(Status, lpErrno, 0, NULL);
 257    }
 258
 259    /* Save Handle */
 260    Socket->Handle = (SOCKET)Sock;
 261
 262    /* Save Group Info */
 263    if (g != 0)
 264    {
 265        GetSocketInformation(Socket, AFD_INFO_GROUP_ID_TYPE, NULL, NULL, &GroupData);
 266        Socket->SharedData.GroupID = GroupData.u.LowPart;
 267        Socket->SharedData.GroupType = GroupData.u.HighPart;
 268    }
 269
 270    /* Get Window Sizes and Save them */
 271    GetSocketInformation (Socket,
 272                          AFD_INFO_SEND_WINDOW_SIZE,
 273                          NULL,
 274                          &Socket->SharedData.SizeOfSendBuffer,
 275                          NULL);
 276
 277    GetSocketInformation (Socket,
 278                          AFD_INFO_RECEIVE_WINDOW_SIZE,
 279                          NULL,
 280                          &Socket->SharedData.SizeOfRecvBuffer,
 281                          NULL);
 282
 283    /* Save in Process Sockets List */
 284    EnterCriticalSection(&SocketListLock);
 285    Socket->NextSocket = SocketListHead;
 286    SocketListHead = Socket;
 287    LeaveCriticalSection(&SocketListLock);
 288
 289    /* Create the Socket Context */
 290    CreateContext(Socket);
 291
 292    /* Notify Winsock */
 293    Upcalls.lpWPUModifyIFSHandle(1, (SOCKET)Sock, lpErrno);
 294
 295    /* Return Socket Handle */
 296    AFD_DbgPrint(MID_TRACE,("Success %x\n", Sock));
 297
 298    return (SOCKET)Sock;
 299
 300error:
 301    AFD_DbgPrint(MID_TRACE,("Ending %x\n", Status));
 302
 303    if( Socket )
 304        HeapFree(GlobalHeap, 0, Socket);
 305
 306    if( lpErrno )
 307        *lpErrno = Status;
 308
 309    return INVALID_SOCKET;
 310}
 311
 312INT
 313TranslateNtStatusError(NTSTATUS Status)
 314{
 315    switch (Status)
 316    {
 317       case STATUS_CANT_WAIT:
 318          return WSAEWOULDBLOCK;
 319
 320       case STATUS_TIMEOUT:
 321          return WSAETIMEDOUT;
 322
 323       case STATUS_SUCCESS:
 324          return NO_ERROR;
 325
 326       case STATUS_FILE_CLOSED:
 327       case STATUS_END_OF_FILE:
 328          return WSAESHUTDOWN;
 329
 330       case STATUS_PENDING:
 331          return WSA_IO_PENDING;
 332
 333       case STATUS_BUFFER_TOO_SMALL:
 334       case STATUS_BUFFER_OVERFLOW:
 335          DbgPrint("MSAFD: STATUS_BUFFER_TOO_SMALL/STATUS_BUFFER_OVERFLOW\n");
 336          return WSAEMSGSIZE;
 337
 338       case STATUS_NO_MEMORY:
 339       case STATUS_INSUFFICIENT_RESOURCES:
 340          DbgPrint("MSAFD: STATUS_NO_MEMORY/STATUS_INSUFFICIENT_RESOURCES\n");
 341          return WSAENOBUFS;
 342
 343       case STATUS_INVALID_CONNECTION:
 344          DbgPrint("MSAFD: STATUS_INVALID_CONNECTION\n");
 345          return WSAEAFNOSUPPORT;
 346
 347       case STATUS_INVALID_ADDRESS:
 348          DbgPrint("MSAFD: STATUS_INVALID_ADDRESS\n");
 349          return WSAEADDRNOTAVAIL;
 350
 351       case STATUS_REMOTE_NOT_LISTENING:
 352          DbgPrint("MSAFD: STATUS_REMOTE_NOT_LISTENING\n");
 353          return WSAECONNREFUSED;
 354
 355       case STATUS_NETWORK_UNREACHABLE:
 356          DbgPrint("MSAFD: STATUS_NETWORK_UNREACHABLE\n");
 357          return WSAENETUNREACH;
 358
 359       case STATUS_INVALID_PARAMETER:
 360          DbgPrint("MSAFD: STATUS_INVALID_PARAMETER\n");
 361          return WSAEINVAL;
 362
 363       case STATUS_CANCELLED:
 364          DbgPrint("MSAFD: STATUS_CANCELLED\n");
 365          return WSA_OPERATION_ABORTED;
 366
 367       case STATUS_ADDRESS_ALREADY_EXISTS:
 368          DbgPrint("MSAFD: STATUS_ADDRESS_ALREADY_EXISTS\n");
 369          return WSAEADDRINUSE;
 370
 371       case STATUS_LOCAL_DISCONNECT:
 372          DbgPrint("MSAFD: STATUS_LOCAL_DISCONNECT\n");
 373          return WSAECONNABORTED;
 374
 375       case STATUS_REMOTE_DISCONNECT:
 376          DbgPrint("MSAFD: STATUS_REMOTE_DISCONNECT\n");
 377          return WSAECONNRESET;
 378
 379       default:
 380          DbgPrint("MSAFD: Unhandled NTSTATUS value: 0x%x\n", Status);
 381          return WSAENETDOWN;
 382    }
 383}
 384
 385/*
 386 * FUNCTION: Closes an open socket
 387 * ARGUMENTS:
 388 *     s       = Socket descriptor
 389 *     lpErrno = Address of buffer for error information
 390 * RETURNS:
 391 *     NO_ERROR, or SOCKET_ERROR if the socket could not be closed
 392 */
 393INT
 394WSPAPI
 395WSPCloseSocket(IN SOCKET Handle,
 396               OUT LPINT lpErrno)
 397{
 398    IO_STATUS_BLOCK IoStatusBlock;
 399    PSOCKET_INFORMATION Socket = NULL, CurrentSocket;
 400    NTSTATUS Status;
 401    HANDLE SockEvent;
 402    AFD_DISCONNECT_INFO DisconnectInfo;
 403    SOCKET_STATE OldState;
 404    LONG LingerWait = -1;
 405
 406    /* Create the Wait Event */
 407    Status = NtCreateEvent(&SockEvent,
 408                           GENERIC_READ | GENERIC_WRITE,
 409                           NULL,
 410                           1,
 411                           FALSE);
 412
 413    if(!NT_SUCCESS(Status))
 414        return SOCKET_ERROR;
 415
 416    /* Get the Socket Structure associate to this Socket*/
 417    Socket = GetSocketStructure(Handle);
 418    if (!Socket)
 419    {
 420       NtClose(SockEvent);
 421       *lpErrno = WSAENOTSOCK;
 422       return SOCKET_ERROR;
 423    }
 424
 425    if (Socket->HelperEvents & WSH_NOTIFY_CLOSE)
 426    {
 427        Status = Socket->HelperData->WSHNotify(Socket->HelperContext,
 428                                               Socket->Handle,
 429                                               Socket->TdiAddressHandle,
 430                                               Socket->TdiConnectionHandle,
 431                                               WSH_NOTIFY_CLOSE);
 432
 433        if (Status)
 434        {
 435            if (lpErrno) *lpErrno = Status;
 436            NtClose(SockEvent);
 437            return SOCKET_ERROR;
 438        }
 439    }
 440
 441    /* If a Close is already in Process, give up */
 442    if (Socket->SharedData.State == SocketClosed)
 443    {
 444        NtClose(SockEvent);
 445        *lpErrno = WSAENOTSOCK;
 446        return SOCKET_ERROR;
 447    }
 448
 449    /* Set the state to close */
 450    OldState = Socket->SharedData.State;
 451    Socket->SharedData.State = SocketClosed;
 452
 453    /* If SO_LINGER is ON and the Socket is connected, we need to disconnect */
 454    /* FIXME: Should we do this on Datagram Sockets too? */
 455    if ((OldState == SocketConnected) && (Socket->SharedData.LingerData.l_onoff))
 456    {
 457        ULONG SendsInProgress;
 458        ULONG SleepWait;
 459
 460        /* We need to respect the timeout */
 461        SleepWait = 100;
 462        LingerWait = Socket->SharedData.LingerData.l_linger * 1000;
 463
 464        /* Loop until no more sends are pending, within the timeout */
 465        while (LingerWait)
 466        {
 467            /* Find out how many Sends are in Progress */
 468            if (GetSocketInformation(Socket,
 469                                     AFD_INFO_SENDS_IN_PROGRESS,
 470                                     NULL,
 471                                     &SendsInProgress,
 472                                     NULL))
 473            {
 474                /* Bail out if anything but NO_ERROR */
 475                LingerWait = 0;
 476                break;
 477            }
 478
 479            /* Bail out if no more sends are pending */
 480            if (!SendsInProgress)
 481            {
 482                LingerWait = -1;
 483                break;
 484            }
 485
 486            /*
 487             * We have to execute a sleep, so it's kind of like
 488             * a block. If the socket is Nonblock, we cannot
 489             * go on since asyncronous operation is expected
 490             * and we cannot offer it
 491             */
 492            if (Socket->SharedData.NonBlocking)
 493            {
 494                NtClose(SockEvent);
 495                Socket->SharedData.State = OldState;
 496                *lpErrno = WSAEWOULDBLOCK;
 497                return SOCKET_ERROR;
 498            }
 499
 500            /* Now we can sleep, and decrement the linger wait */
 501            /*
 502            * FIXME: It seems Windows does some funky acceleration
 503            * since the waiting seems to be longer and longer. I
 504            * don't think this improves performance so much, so we
 505            * wait a fixed time instead.
 506            */
 507            Sleep(SleepWait);
 508            LingerWait -= SleepWait;
 509        }
 510    }
 511
 512    if (OldState == SocketConnected)
 513    {
 514        if (LingerWait <= 0)
 515        {
 516            DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(0);
 517            DisconnectInfo.DisconnectType = LingerWait < 0 ? AFD_DISCONNECT_SEND : AFD_DISCONNECT_ABORT;
 518
 519            if (((DisconnectInfo.DisconnectType & AFD_DISCONNECT_SEND) && (!Socket->SharedData.SendShutdown)) ||
 520                ((DisconnectInfo.DisconnectType & AFD_DISCONNECT_ABORT) && (!Socket->SharedData.ReceiveShutdown)))
 521            {
 522                /* Send IOCTL */
 523                Status = NtDeviceIoControlFile((HANDLE)Handle,
 524                                               SockEvent,
 525                                               NULL,
 526                                               NULL,
 527                                               &IoStatusBlock,
 528                                               IOCTL_AFD_DISCONNECT,
 529                                               &DisconnectInfo,
 530                                               sizeof(DisconnectInfo),
 531                                               NULL,
 532                                               0);
 533
 534                /* Wait for return */
 535                if (Status == STATUS_PENDING)
 536                {
 537                    WaitForSingleObject(SockEvent, INFINITE);
 538                    Status = IoStatusBlock.Status;
 539                }
 540            }
 541        }
 542    }
 543
 544    /* Cleanup Time! */
 545    Socket->HelperContext = NULL;
 546    Socket->SharedData.AsyncDisabledEvents = -1;
 547    NtClose(Socket->TdiAddressHandle);
 548    Socket->TdiAddressHandle = NULL;
 549    NtClose(Socket->TdiConnectionHandle);
 550    Socket->TdiConnectionHandle = NULL;
 551
 552    EnterCriticalSection(&SocketListLock);
 553    if (SocketListHead == Socket)
 554    {
 555        SocketListHead = SocketListHead->NextSocket;
 556    }
 557    else
 558    {
 559        CurrentSocket = SocketListHead;
 560        while (CurrentSocket->NextSocket)
 561        {
 562            if (CurrentSocket->NextSocket == Socket)
 563            {
 564                CurrentSocket->NextSocket = CurrentSocket->NextSocket->NextSocket;
 565                break;
 566            }
 567
 568            CurrentSocket = CurrentSocket->NextSocket;
 569        }
 570    }
 571    LeaveCriticalSection(&SocketListLock);
 572
 573    /* Close the handle */
 574    NtClose((HANDLE)Handle);
 575    NtClose(SockEvent);
 576
 577    HeapFree(GlobalHeap, 0, Socket);
 578    return MsafdReturnWithErrno(Status, lpErrno, 0, NULL);
 579}
 580
 581
 582/*
 583 * FUNCTION: Associates a local address with a socket
 584 * ARGUMENTS:
 585 *     s       = Socket descriptor
 586 *     name    = Pointer to local address
 587 *     namelen = Length of name
 588 *     lpErrno = Address of buffer for error information
 589 * RETURNS:
 590 *     0, or SOCKET_ERROR if the socket could not be bound
 591 */
 592INT
 593WSPAPI
 594WSPBind(SOCKET Handle,
 595        const struct sockaddr *SocketAddress,
 596        int SocketAddressLength,
 597        LPINT lpErrno)
 598{
 599    IO_STATUS_BLOCK         IOSB;
 600    PAFD_BIND_DATA          BindData;
 601    PSOCKET_INFORMATION     Socket = NULL;
 602    NTSTATUS                Status;
 603    SOCKADDR_INFO           SocketInfo;
 604    HANDLE                  SockEvent;
 605
 606    /* See below */
 607    BindData = HeapAlloc(GlobalHeap, 0, 0xA + SocketAddressLength);
 608    if (!BindData)
 609    {
 610        return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL);
 611    }
 612
 613    Status = NtCreateEvent(&SockEvent,
 614                           GENERIC_READ | GENERIC_WRITE,
 615                           NULL,
 616                           1,
 617                           FALSE);
 618
 619    if (!NT_SUCCESS(Status))
 620    {
 621        HeapFree(GlobalHeap, 0, BindData);
 622        return SOCKET_ERROR;
 623    }
 624
 625    /* Get the Socket Structure associate to this Socket*/
 626    Socket = GetSocketStructure(Handle);
 627    if (!Socket)
 628    {
 629       HeapFree(GlobalHeap, 0, BindData);
 630       *lpErrno = WSAENOTSOCK;
 631       return SOCKET_ERROR;
 632    }
 633
 634    /* Set up Address in TDI Format */
 635    BindData->Address.TAAddressCount = 1;
 636    BindData->Address.Address[0].AddressLength = SocketAddressLength - sizeof(SocketAddress->sa_family);
 637    BindData->Address.Address[0].AddressType = SocketAddress->sa_family;
 638    RtlCopyMemory (BindData->Address.Address[0].Address,
 639                   SocketAddress->sa_data,
 640                   SocketAddressLength - sizeof(SocketAddress->sa_family));
 641
 642    /* Get Address Information */
 643    Socket->HelperData->WSHGetSockaddrType ((PSOCKADDR)SocketAddress,
 644                                            SocketAddressLength,
 645                                            &SocketInfo);
 646
 647    /* Set the Share Type */
 648    if (Socket->SharedData.ExclusiveAddressUse)
 649    {
 650        BindData->ShareType = AFD_SHARE_EXCLUSIVE;
 651    }
 652    else if (SocketInfo.EndpointInfo == SockaddrEndpointInfoWildcard)
 653    {
 654        BindData->ShareType = AFD_SHARE_WILDCARD;
 655    }
 656    else if (Socket->SharedData.ReuseAddresses)
 657    {
 658        BindData->ShareType = AFD_SHARE_REUSE;
 659    }
 660    else
 661    {
 662        BindData->ShareType = AFD_SHARE_UNIQUE;
 663    }
 664
 665    /* Send IOCTL */
 666    Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
 667                                   SockEvent,
 668                                   NULL,
 669                                   NULL,
 670                                   &IOSB,
 671                                   IOCTL_AFD_BIND,
 672                                   BindData,
 673                                   0xA + Socket->SharedData.SizeOfLocalAddress, /* Can't figure out a way to calculate this in C*/
 674                                   BindData,
 675                                   0xA + Socket->SharedData.SizeOfLocalAddress); /* Can't figure out a way to calculate this C */
 676
 677    /* Wait for return */
 678    if (Status == STATUS_PENDING)
 679    {
 680        WaitForSingleObject(SockEvent, INFINITE);
 681        Status = IOSB.Status;
 682    }
 683
 684    NtClose( SockEvent );
 685    HeapFree(GlobalHeap, 0, BindData);
 686
 687    if (Status != STATUS_SUCCESS)
 688        return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL );
 689
 690    /* Set up Socket Data */
 691    Socket->SharedData.State = SocketBound;
 692    Socket->TdiAddressHandle = (HANDLE)IOSB.Information;
 693
 694    if (Socket->HelperEvents & WSH_NOTIFY_BIND)
 695    {
 696        Status = Socket->HelperData->WSHNotify(Socket->HelperContext,
 697                                               Socket->Handle,
 698                                               Socket->TdiAddressHandle,
 699                                               Socket->TdiConnectionHandle,
 700                                               WSH_NOTIFY_BIND);
 701
 702        if (Status)
 703        {
 704            if (lpErrno) *lpErrno = Status;
 705            return SOCKET_ERROR;
 706        }
 707    }
 708
 709    return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL );
 710}
 711
 712int
 713WSPAPI
 714WSPListen(SOCKET Handle,
 715          int Backlog,
 716          LPINT lpErrno)
 717{
 718    IO_STATUS_BLOCK         IOSB;
 719    AFD_LISTEN_DATA         ListenData;
 720    PSOCKET_INFORMATION     Socket = NULL;
 721    HANDLE                  SockEvent;
 722    NTSTATUS                Status;
 723
 724    /* Get the Socket Structure associate to this Socket*/
 725    Socket = GetSocketStructure(Handle);
 726    if (!Socket)
 727    {
 728       *lpErrno = WSAENOTSOCK;
 729       return SOCKET_ERROR;
 730    }
 731
 732    if (Socket->SharedData.Listening)
 733        return 0;
 734
 735    Status = NtCreateEvent(&SockEvent,
 736                           GENERIC_READ | GENERIC_WRITE,
 737                           NULL,
 738                           1,
 739                           FALSE);
 740
 741    if( !NT_SUCCESS(Status) )
 742        return -1;
 743
 744    /* Set Up Listen Structure */
 745    ListenData.UseSAN = FALSE;
 746    ListenData.UseDelayedAcceptance = Socket->SharedData.UseDelayedAcceptance;
 747    ListenData.Backlog = Backlog;
 748
 749    /* Send IOCTL */
 750    Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
 751                                   SockEvent,
 752                                   NULL,
 753                                   NULL,
 754                                   &IOSB,
 755                                   IOCTL_AFD_START_LISTEN,
 756                                   &ListenData,
 757                                   sizeof(ListenData),
 758                                   NULL,
 759                                   0);
 760
 761    /* Wait for return */
 762    if (Status == STATUS_PENDING)
 763    {
 764        WaitForSingleObject(SockEvent, INFINITE);
 765        Status = IOSB.Status;
 766    }
 767
 768    NtClose( SockEvent );
 769
 770    if (Status != STATUS_SUCCESS)
 771       return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL );
 772
 773    /* Set to Listening */
 774    Socket->SharedData.Listening = TRUE;
 775
 776    if (Socket->HelperEvents & WSH_NOTIFY_LISTEN)
 777    {
 778        Status = Socket->HelperData->WSHNotify(Socket->HelperContext,
 779                                               Socket->Handle,
 780                                               Socket->TdiAddressHandle,
 781                                               Socket->TdiConnectionHandle,
 782                                               WSH_NOTIFY_LISTEN);
 783
 784        if (Status)
 785        {
 786           if (lpErrno) *lpErrno = Status;
 787           return SOCKET_ERROR;
 788        }
 789    }
 790
 791    return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL );
 792}
 793
 794
 795int
 796WSPAPI
 797WSPSelect(IN int nfds,
 798          IN OUT fd_set *readfds OPTIONAL,
 799          IN OUT fd_set *writefds OPTIONAL,
 800          IN OUT fd_set *exceptfds OPTIONAL,
 801          IN const struct timeval *timeout OPTIONAL,
 802          OUT LPINT lpErrno)
 803{
 804    IO_STATUS_BLOCK     IOSB;
 805    PAFD_POLL_INFO      PollInfo;
 806    NTSTATUS            Status;
 807    ULONG               HandleCount;
 808    LONG                OutCount = 0;
 809    ULONG               PollBufferSize;
 810    PVOID               PollBuffer;
 811    ULONG               i, j = 0, x;
 812    HANDLE              SockEvent;
 813    BOOL                HandleCounted;
 814    LARGE_INTEGER       Timeout;
 815
 816    /* Find out how many sockets we have, and how large the buffer needs
 817     * to be */
 818
 819    HandleCount = ( readfds ? readfds->fd_count : 0 ) +
 820                  ( writefds ? writefds->fd_count : 0 ) +
 821                  ( exceptfds ? exceptfds->fd_count : 0 );
 822
 823    if ( HandleCount == 0 )
 824    {
 825        AFD_DbgPrint(MAX_TRACE,("HandleCount: %u. Return SOCKET_ERROR\n",
 826                     HandleCount));
 827        if (lpErrno) *lpErrno = WSAEINVAL;
 828        return SOCKET_ERROR;
 829    }
 830
 831    PollBufferSize = sizeof(*PollInfo) + ((HandleCount - 1) * sizeof(AFD_HANDLE));
 832
 833    AFD_DbgPrint(MID_TRACE,("HandleCount: %u BufferSize: %u\n",
 834                 HandleCount, PollBufferSize));
 835
 836    /* Convert Timeout to NT Format */
 837    if (timeout == NULL)
 838    {
 839        Timeout.u.LowPart = -1;
 840        Timeout.u.HighPart = 0x7FFFFFFF;
 841        AFD_DbgPrint(MAX_TRACE,("Infinite timeout\n"));
 842    }
 843    else
 844    {
 845        Timeout = RtlEnlargedIntegerMultiply
 846            ((timeout->tv_sec * 1000) + (timeout->tv_usec / 1000), -10000);
 847        /* Negative timeouts are illegal.  Since the kernel represents an
 848         * incremental timeout as a negative number, we check for a positive
 849         * result.
 850         */
 851        if (Timeout.QuadPart > 0)
 852        {
 853            if (lpErrno) *lpErrno = WSAEINVAL;
 854                return SOCKET_ERROR;
 855        }
 856        AFD_DbgPrint(MAX_TRACE,("Timeout: Orig %d.%06d kernel %d\n",
 857                     timeout->tv_sec, timeout->tv_usec,
 858                     Timeout.u.LowPart));
 859    }
 860
 861    Status = NtCreateEvent(&SockEvent,
 862                           GENERIC_READ | GENERIC_WRITE,
 863                           NULL,
 864                           1,
 865                           FALSE);
 866
 867    if( !NT_SUCCESS(Status) )
 868        return SOCKET_ERROR;
 869
 870    /* Allocate */
 871    PollBuffer = HeapAlloc(GlobalHeap, 0, PollBufferSize);
 872
 873    if (!PollBuffer)
 874    {
 875        if (lpErrno)
 876            *lpErrno = WSAEFAULT;
 877        NtClose(SockEvent);
 878        return SOCKET_ERROR;
 879    }
 880
 881    PollInfo = (PAFD_POLL_INFO)PollBuffer;
 882
 883    RtlZeroMemory( PollInfo, PollBufferSize );
 884
 885    /* Number of handles for AFD to Check */
 886    PollInfo->Exclusive = FALSE;
 887    PollInfo->Timeout = Timeout;
 888
 889    if (readfds != NULL) {
 890        for (i = 0; i < readfds->fd_count; i++, j++)
 891        {
 892            PollInfo->Handles[j].Handle = readfds->fd_array[i];
 893            PollInfo->Handles[j].Events = AFD_EVENT_RECEIVE |
 894                                          AFD_EVENT_DISCONNECT |
 895                                          AFD_EVENT_ABORT |
 896                                          AFD_EVENT_CLOSE |
 897                                          AFD_EVENT_ACCEPT;
 898        }
 899    }
 900    if (writefds != NULL)
 901    {
 902        for (i = 0; i < writefds->fd_count; i++, j++)
 903        {
 904            PollInfo->Handles[j].Handle = writefds->fd_array[i];
 905            PollInfo->Handles[j].Events = AFD_EVENT_SEND | AFD_EVENT_CONNECT;
 906        }
 907    }
 908    if (exceptfds != NULL)
 909    {
 910        for (i = 0; i < exceptfds->fd_count; i++, j++)
 911        {
 912            PollInfo->Handles[j].Handle = exceptfds->fd_array[i];
 913            PollInfo->Handles[j].Events = AFD_EVENT_OOB_RECEIVE | AFD_EVENT_CONNECT_FAIL;
 914        }
 915    }
 916
 917    PollInfo->HandleCount = j;
 918    PollBufferSize = FIELD_OFFSET(AFD_POLL_INFO, Handles) + PollInfo->HandleCount * sizeof(AFD_HANDLE);
 919
 920    /* Send IOCTL */
 921    Status = NtDeviceIoControlFile((HANDLE)PollInfo->Handles[0].Handle,
 922                                   SockEvent,
 923                                   NULL,
 924                                   NULL,
 925                                   &IOSB,
 926                                   IOCTL_AFD_SELECT,
 927                                   PollInfo,
 928                                   PollBufferSize,
 929                                   PollInfo,
 930                                   PollBufferSize);
 931
 932    AFD_DbgPrint(MID_TRACE,("DeviceIoControlFile => %x\n", Status));
 933
 934    /* Wait for Completition */
 935    if (Status == STATUS_PENDING)
 936    {
 937        WaitForSingleObject(SockEvent, INFINITE);
 938        Status = IOSB.Status;
 939    }
 940
 941    /* Clear the Structures */
 942    if( readfds )
 943        FD_ZERO(readfds);
 944    if( writefds )
 945        FD_ZERO(writefds);
 946    if( exceptfds )
 947        FD_ZERO(exceptfds);
 948
 949    /* Loop through return structure */
 950    HandleCount = PollInfo->HandleCount;
 951
 952    /* Return in FDSET Format */
 953    for (i = 0; i < HandleCount; i++)
 954    {
 955        HandleCounted = FALSE;
 956        for(x = 1; x; x<<=1)
 957        {
 958            switch (PollInfo->Handles[i].Events & x)
 959            {
 960                case AFD_EVENT_RECEIVE:
 961                case AFD_EVENT_DISCONNECT:
 962                case AFD_EVENT_ABORT:
 963                case AFD_EVENT_ACCEPT:
 964                case AFD_EVENT_CLOSE:
 965                    AFD_DbgPrint(MID_TRACE,("Event %x on handle %x\n",
 966                                 PollInfo->Handles[i].Events,
 967                                 PollInfo->Handles[i].Handle));
 968                    if (! HandleCounted)
 969                    {
 970                        OutCount++;
 971                        HandleCounted = TRUE;
 972                    }
 973                    if( readfds )
 974                        FD_SET(PollInfo->Handles[i].Handle, readfds);
 975                    break;
 976                case AFD_EVENT_SEND:
 977                case AFD_EVENT_CONNECT:
 978                    AFD_DbgPrint(MID_TRACE,("Event %x on handle %x\n",
 979                                 PollInfo->Handles[i].Events,
 980                                 PollInfo->Handles[i].Handle));
 981                    if (! HandleCounted)
 982                    {
 983                        OutCount++;
 984                        HandleCounted = TRUE;
 985                    }
 986                    if( writefds )
 987                        FD_SET(PollInfo->Handles[i].Handle, writefds);
 988                    break;
 989                case AFD_EVENT_OOB_RECEIVE:
 990                case AFD_EVENT_CONNECT_FAIL:
 991                    AFD_DbgPrint(MID_TRACE,("Event %x on handle %x\n",
 992                                 PollInfo->Handles[i].Events,
 993                                 PollInfo->Handles[i].Handle));
 994                    if (! HandleCounted)
 995                    {
 996                        OutCount++;
 997                        HandleCounted = TRUE;
 998                    }
 999                    if( exceptfds )
1000                        FD_SET(PollInfo->Handles[i].Handle, exceptfds);
1001                    break;
1002            }
1003        }
1004    }
1005
1006    HeapFree( GlobalHeap, 0, PollBuffer );
1007    NtClose( SockEvent );
1008
1009    if( lpErrno )
1010    {
1011        switch( IOSB.Status )
1012        {
1013            case STATUS_SUCCESS:
1014            case STATUS_TIMEOUT:
1015                *lpErrno = 0;
1016                break;
1017            default:
1018                *lpErrno = WSAEINVAL;
1019                break;
1020        }
1021        AFD_DbgPrint(MID_TRACE,("*lpErrno = %x\n", *lpErrno));
1022    }
1023
1024    AFD_DbgPrint(MID_TRACE,("%d events\n", OutCount));
1025
1026    return OutCount;
1027}
1028
1029SOCKET
1030WSPAPI
1031WSPAccept(SOCKET Handle,
1032          struct sockaddr *SocketAddress,
1033          int *SocketAddressLength,
1034          LPCONDITIONPROC lpfnCondition,
1035          DWORD dwCallbackData,
1036          LPINT lpErrno)
1037{
1038    IO_STATUS_BLOCK             IOSB;
1039    PAFD_RECEIVED_ACCEPT_DATA   ListenReceiveData;
1040    AFD_ACCEPT_DATA             AcceptData;
1041    AFD_DEFER_ACCEPT_DATA       DeferData;
1042    AFD_PENDING_ACCEPT_DATA     PendingAcceptData;
1043    PSOCKET_INFORMATION         Socket = NULL;
1044    NTSTATUS                    Status;
1045    struct fd_set               ReadSet;
1046    struct timeval              Timeout;
1047    PVOID                       PendingData = NULL;
1048    ULONG                       PendingDataLength = 0;
1049    PVOID                       CalleeDataBuffer;
1050    WSABUF                      CallerData, CalleeID, CallerID, CalleeData;
1051    PSOCKADDR                   RemoteAddress =  NULL;
1052    GROUP                       GroupID = 0;
1053    ULONG                       CallBack;
1054    WSAPROTOCOL_INFOW           ProtocolInfo;
1055    SOCKET                      AcceptSocket;
1056    PSOCKET_INFORMATION         AcceptSocketInfo;
1057    UCHAR                       ReceiveBuffer[0x1A];
1058    HANDLE                      SockEvent;
1059
1060    Status = NtCreateEvent(&SockEvent,
1061                           GENERIC_READ | GENERIC_WRITE,
1062                           NULL,
1063                           1,
1064                           FALSE);
1065
1066    if( !NT_SUCCESS(Status) )
1067    {
1068        MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
1069        return INVALID_SOCKET;
1070    }
1071
1072    /* Dynamic Structure...ugh */
1073    ListenReceiveData = (PAFD_RECEIVED_ACCEPT_DATA)ReceiveBuffer;
1074
1075    /* Get the Socket Structure associate to this Socket*/
1076    Socket = GetSocketStructure(Handle);
1077    if (!Socket)
1078    {
1079       NtClose(SockEvent);
1080       *lpErrno = WSAENOTSOCK;
1081       return INVALID_SOCKET;
1082    }
1083
1084    /* If this is non-blocking, make sure there's something for us to accept */
1085    FD_ZERO(&ReadSet);
1086    FD_SET(Socket->Handle, &ReadSet);
1087    Timeout.tv_sec=0;
1088    Timeout.tv_usec=0;
1089
1090    if (WSPSelect(0, &ReadSet, NULL, NULL, &Timeout, lpErrno) == SOCKET_ERROR)
1091    {
1092        NtClose(SockEvent);
1093        return INVALID_SOCKET;
1094    }
1095
1096    if (ReadSet.fd_array[0] != Socket->Handle)
1097    {
1098        NtClose(SockEvent);
1099        *lpErrno = WSAEWOULDBLOCK;
1100        return INVALID_SOCKET;
1101    }
1102
1103    /* Send IOCTL */
1104    Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
1105                                   SockEvent,
1106                                   NULL,
1107                                   NULL,
1108                                   &IOSB,
1109                                   IOCTL_AFD_WAIT_FOR_LISTEN,
1110                                   NULL,
1111                                   0,
1112                                   ListenReceiveData,
1113                                   0xA + sizeof(*ListenReceiveData));
1114
1115    /* Wait for return */
1116    if (Status == STATUS_PENDING)
1117    {
1118        WaitForSingleObject(SockEvent, INFINITE);
1119        Status = IOSB.Status;
1120    }
1121
1122    if (!NT_SUCCESS(Status))
1123    {
1124        NtClose( SockEvent );
1125        MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
1126        return INVALID_SOCKET;
1127    }
1128
1129    if (lpfnCondition != NULL)
1130    {
1131        if ((Socket->SharedData.ServiceFlags1 & XP1_CONNECT_DATA) != 0)
1132        {
1133            /* Find out how much data is pending */
1134            PendingAcceptData.SequenceNumber = ListenReceiveData->SequenceNumber;
1135            PendingAcceptData.ReturnSize = TRUE;
1136
1137            /* Send IOCTL */
1138            Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
1139                                           SockEvent,
1140                                           NULL,
1141                                           NULL,
1142                                           &IOSB,
1143                                           IOCTL_AFD_GET_PENDING_CONNECT_DATA,
1144                                           &PendingAcceptData,
1145                                           sizeof(PendingAcceptData),
1146                                           &PendingAcceptData,
1147                                           sizeof(PendingAcceptData));
1148
1149            /* Wait for return */
1150            if (Status == STATUS_PENDING)
1151            {
1152                WaitForSingleObject(SockEvent, INFINITE);
1153                Status = IOSB.Status;
1154            }
1155
1156            if (!NT_SUCCESS(Status))
1157            {
1158                NtClose( SockEvent );
1159                MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
1160                return INVALID_SOCKET;
1161            }
1162
1163            /* How much data to allocate */
1164            PendingDataLength = IOSB.Information;
1165
1166            if (PendingDataLength)
1167            {
1168                /* Allocate needed space */
1169                PendingData = HeapAlloc(GlobalHeap, 0, PendingDataLength);
1170                if (!PendingData)
1171                {
1172                    MsafdReturnWithErrno( STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL );
1173                    return INVALID_SOCKET;
1174                }
1175
1176                /* We want the data now */
1177                PendingAcceptData.ReturnSize = FALSE;
1178
1179                /* Send IOCTL */
1180                Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
1181                                               SockEvent,
1182                                               NULL,
1183                                               NULL,
1184                                               &IOSB,
1185                                               IOCTL_AFD_GET_PENDING_CONNECT_DATA,
1186                                               &PendingAcceptData,
1187                                               sizeof(PendingAcceptData),
1188                                               PendingData,
1189                                               PendingDataLength);
1190
1191                /* Wait for return */
1192                if (Status == STATUS_PENDING)
1193                {
1194                    WaitForSingleObject(SockEvent, INFINITE);
1195                    Status = IOSB.Status;
1196                }
1197
1198                if (!NT_SUCCESS(Status))
1199                {
1200                    NtClose( SockEvent );
1201                    MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
1202                    return INVALID_SOCKET;
1203                }
1204            }
1205        }
1206
1207        if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED) != 0)
1208        {
1209            /* I don't support this yet */
1210        }
1211
1212        /* Build Callee ID */
1213        CalleeID.buf = (PVOID)Socket->LocalAddress;
1214        CalleeID.len = Socket->SharedData.SizeOfLocalAddress;
1215
1216        RemoteAddress = HeapAlloc(GlobalHeap, 0, sizeof(*RemoteAddress));
1217        if (!RemoteAddress)
1218        {
1219            MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL);
1220            return INVALID_SOCKET;
1221        }
1222
1223        /* Set up Address in SOCKADDR Format */
1224        RtlCopyMemory (RemoteAddress,
1225                       &ListenReceiveData->Address.Address[0].AddressType,
1226                       sizeof(*RemoteAddress));
1227
1228        /* Build Caller ID */
1229        CallerID.buf = (PVOID)RemoteAddress;
1230        CallerID.len = sizeof(*RemoteAddress);
1231
1232        /* Build Caller Data */
1233        CallerData.buf = PendingData;
1234        CallerData.len = PendingDataLength;
1235
1236        /* Check if socket supports Conditional Accept */
1237        if (Socket->SharedData.UseDelayedAcceptance != 0)
1238        {
1239            /* Allocate Buffer for Callee Data */
1240            CalleeDataBuffer = HeapAlloc(GlobalHeap, 0, 4096);
1241            if (!CalleeDataBuffer) {
1242                MsafdReturnWithErrno( STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL );
1243                return INVALID_SOCKET;
1244            }
1245            CalleeData.buf = CalleeDataBuffer;
1246            CalleeData.len = 4096;
1247        }
1248        else
1249        {
1250            /* Nothing */
1251            CalleeData.buf = 0;
1252            CalleeData.len = 0;
1253        }
1254
1255        /* Call the Condition Function */
1256        CallBack = (lpfnCondition)(&CallerID,
1257                                   CallerData.buf == NULL ? NULL : &CallerData,
1258                                   NULL,
1259                                   NULL,
1260                                   &CalleeID,
1261                                   CalleeData.buf == NULL ? NULL : &CalleeData,
1262                                   &GroupID,
1263                                   dwCallbackData);
1264
1265        if (((CallBack == CF_ACCEPT) && GroupID) != 0)
1266        {
1267            /* TBD: Check for Validity */
1268        }
1269
1270        if (CallBack == CF_ACCEPT)
1271        {
1272            if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED) != 0)
1273            {
1274                /* I don't support this yet */
1275            }
1276            if (CalleeData.buf)
1277            {
1278                // SockSetConnectData Sockets(SocketID), IOCTL_AFD_SET_CONNECT_DATA, CalleeData.Buffer, CalleeData.BuffSize, 0
1279            }
1280        }
1281        else
1282        {
1283            /* Callback rejected. Build Defer Structure */
1284            DeferData.SequenceNumber = ListenReceiveData->SequenceNumber;
1285            DeferData.RejectConnection = (CallBack == CF_REJECT);
1286
1287            /* Send IOCTL */
1288            Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
1289                                           SockEvent,
1290                                           NULL,
1291                                           NULL,
1292                                           &IOSB,
1293                                           IOCTL_AFD_DEFER_ACCEPT,
1294                                           &DeferData,
1295                                           sizeof(DeferData),
1296                                           NULL,
1297                                           0);
1298
1299            /* Wait for return */
1300            if (Status == STATUS_PENDING)
1301            {
1302                WaitForSingleObject(SockEvent, INFINITE);
1303                Status = IOSB.Status;
1304            }
1305
1306            NtClose( SockEvent );
1307
1308            if (!NT_SUCCESS(Status))
1309            {
1310                MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
1311                return INVALID_SOCKET;
1312            }
1313
1314            if (CallBack == CF_REJECT )
1315            {
1316                *lpErrno = WSAECONNREFUSED;
1317                return INVALID_SOCKET;
1318            }
1319            else
1320            {
1321                *lpErrno = WSAECONNREFUSED;
1322                return INVALID_SOCKET;
1323            }
1324        }
1325    }
1326
1327    /* Create a new Socket */
1328    ProtocolInfo.dwCatalogEntryId = Socket->SharedData.CatalogEntryId;
1329    ProtocolInfo.dwServiceFlags1 = Socket->SharedData.ServiceFlags1;
1330    ProtocolInfo.dwProviderFlags = Socket->SharedData.ProviderFlags;
1331
1332    AcceptSocket = WSPSocket (Socket->SharedData.AddressFamily,
1333                              Socket->SharedData.SocketType,
1334                              Socket->SharedData.Protocol,
1335                              &ProtocolInfo,
1336                              GroupID,
1337                              Socket->SharedData.CreateFlags,
1338                              lpErrno);
1339    if (AcceptSocket == INVALID_SOCKET)
1340        return INVALID_SOCKET;
1341
1342    /* Set up the Accept Structure */
1343    AcceptData.ListenHandle = (HANDLE)AcceptSocket;
1344    AcceptData.SequenceNumber = ListenReceiveData->SequenceNumber;
1345
1346    /* Send IOCTL to Accept */
1347    Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
1348                                   SockEvent,
1349                                   NULL,
1350                                   NULL,
1351                                   &IOSB,
1352                                   IOCTL_AFD_ACCEPT,
1353                                   &AcceptData,
1354                                   sizeof(AcceptData),
1355                                   NULL,
1356                                   0);
1357
1358    /* Wait for return */
1359    if (Status == STATUS_PENDING)
1360    {
1361        WaitForSingleObject(SockEvent, INFINITE);
1362        Status = IOSB.Status;
1363    }
1364
1365    if (!NT_SUCCESS(Status))
1366    {
1367        NtClose(SockEvent);
1368        WSPCloseSocket( AcceptSocket, lpErrno );
1369        MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
1370        return INVALID_SOCKET;
1371    }
1372
1373    AcceptSocketInfo = GetSocketStructure(AcceptSocket);
1374    if (!AcceptSocketInfo)
1375    {
1376        NtClose(SockEvent);
1377        WSPCloseSocket( AcceptSocket, lpErrno );
1378        MsafdReturnWithErrno( STATUS_INVALID_CONNECTION, lpErrno, 0, NULL );
1379        return INVALID_SOCKET;
1380    }
1381
1382    AcceptSocketInfo->SharedData.State = SocketConnected;
1383
1384    /* Return Address in SOCKADDR FORMAT */
1385    if( SocketAddress )
1386    {
1387        RtlCopyMemory (SocketAddress,
1388                       &ListenReceiveData->Address.Address[0].AddressType,
1389                       sizeof(*RemoteAddress));
1390        if( SocketAddressLength )
1391            *SocketAddressLength = ListenReceiveData->Address.Address[0].AddressLength;
1392    }
1393
1394    NtClose( SockEvent );
1395
1396    /* Re-enable Async Event */
1397    SockReenableAsyncSelectEvent(Socket, FD_ACCEPT);
1398
1399    AFD_DbgPrint(MID_TRACE,("Socket %x\n", AcceptSocket));
1400
1401    if (Status == STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_ACCEPT))
1402    {
1403        Status = Socket->HelperData->WSHNotify(Socket->HelperContext,
1404                                               Socket->Handle,
1405                                               Socket->TdiAddressHandle,
1406                                               Socket->TdiConnectionHandle,
1407                                               WSH_NOTIFY_ACCEPT);
1408
1409        if (Status)
1410        {
1411            if (lpErrno) *lpErrno = Status;
1412            return INVALID_SOCKET;
1413        }
1414    }
1415
1416    *lpErrno = 0;
1417
1418    /* Return Socket */
1419    return AcceptSocket;
1420}
1421
1422int
1423WSPAPI
1424WSPConnect(SOCKET Handle,
1425           const struct sockaddr * SocketAddress,
1426           int SocketAddressLength,
1427           LPWSABUF lpCallerData,
1428           LPWSABUF lpCalleeData,
1429           LPQOS lpSQOS,
1430           LPQOS lpGQOS,
1431           LPINT lpErrno)
1432{
1433    IO_STATUS_BLOCK         IOSB;
1434    PAFD_CONNECT_INFO       ConnectInfo = NULL;
1435    PSOCKET_INFORMATION     Socket;
1436    NTSTATUS                Status;
1437    INT                     Errno;
1438    ULONG                   ConnectDataLength;
1439    ULONG                   InConnectDataLength;
1440    INT                     BindAddressLength;
1441    PSOCKADDR               BindAddress;
1442    HANDLE                  SockEvent;
1443    int                     SocketDataLength;
1444
1445    Status = NtCreateEvent(&SockEvent,
1446                           GENERIC_READ | GENERIC_WRITE,
1447                           NULL,
1448                           1,
1449                           FALSE);
1450
1451    if (!NT_SUCCESS(Status))
1452        return MsafdReturnWithErrno(Status, lpErrno, 0, NULL);
1453
1454    AFD_DbgPrint(MID_TRACE,("Called\n"));
1455
1456    /* Get the Socket Structure associate to this Socket*/
1457    Socket = GetSocketStructure(Handle);
1458    if (!Socket)
1459    {
1460        NtClose(SockEvent);
1461        if (lpErrno) *lpErrno = WSAENOTSOCK;
1462        return SOCKET_ERROR;
1463    }
1464
1465    /* Bind us First */
1466    if (Socket->SharedData.State == SocketOpen)
1467    {
1468        /* Get the Wildcard Address */
1469        BindAddressLength = Socket->HelperData->MaxWSAddressLength;
1470        BindAddress = HeapAlloc(GetProcessHeap(), 0, BindAddressLength);
1471        if (!BindAddress)
1472        {
1473            NtClose(SockEvent);
1474            return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL);
1475        }
1476        Socket->HelperData->WSHGetWildcardSockaddr (Socket->HelperContext,
1477                                                    BindAddress,
1478                                                    &BindAddressLength);
1479        /* Bind it */
1480        if (WSPBind(Handle, BindAddress, BindAddressLength, lpErrno) == SOCKET_ERROR)
1481            return SOCKET_ERROR;
1482    }
1483
1484    /* Set the Connect Data */
1485    if (lpCallerData != NULL)
1486    {
1487        ConnectDataLength = lpCallerData->len;
1488        Status = NtDeviceIoControlFile((HANDLE)Handle,
1489                                        SockEvent,
1490                                        NULL,
1491                                        NULL,
1492                                        &IOSB,
1493                                        IOCTL_AFD_SET_CONNECT_DATA,
1494                                        lpCallerData->buf,
1495                                        ConnectDataLength,
1496                                        NULL,
1497                                        0);
1498        /* Wait for return */
1499        if (Status == STATUS_PENDING)
1500        {
1501            WaitForSingleObject(SockEvent, INFINITE);
1502            Status = IOSB.Status;
1503        }
1504
1505        if (Status != STATUS_SUCCESS)
1506            goto notify;
1507    }
1508
1509    /* Calculate the size of SocketAddress->sa_data */
1510    SocketDataLength = SocketAddres

Large files files are truncated, but you can click here to view the full file