ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

dllmain.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:   See COPYING in the top level directory
00003  * PROJECT:     ReactOS Ancillary Function Driver DLL
00004  * FILE:        misc/dllmain.c
00005  * PURPOSE:     DLL entry point
00006  * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
00007  *              Alex Ionescu (alex@relsoft.net)
00008  * REVISIONS:
00009  *              CSH 01/09-2000 Created
00010  *              Alex 16/07/2004 - Complete Rewrite
00011  */
00012 
00013 #include <msafd.h>
00014 
00015 #if DBG
00016 //DWORD DebugTraceLevel = DEBUG_ULTRA;
00017 DWORD DebugTraceLevel = 0;
00018 #endif /* DBG */
00019 
00020 HANDLE GlobalHeap;
00021 WSPUPCALLTABLE Upcalls;
00022 LPWPUCOMPLETEOVERLAPPEDREQUEST lpWPUCompleteOverlappedRequest;
00023 PSOCKET_INFORMATION SocketListHead = NULL;
00024 CRITICAL_SECTION SocketListLock;
00025 LIST_ENTRY SockHelpersListHead = { NULL, NULL };
00026 ULONG SockAsyncThreadRefCount;
00027 HANDLE SockAsyncHelperAfdHandle;
00028 HANDLE SockAsyncCompletionPort = NULL;
00029 BOOLEAN SockAsyncSelectCalled;
00030 
00031 
00032 
00033 /*
00034  * FUNCTION: Creates a new socket
00035  * ARGUMENTS:
00036  *     af             = Address family
00037  *     type           = Socket type
00038  *     protocol       = Protocol type
00039  *     lpProtocolInfo = Pointer to protocol information
00040  *     g              = Reserved
00041  *     dwFlags        = Socket flags
00042  *     lpErrno        = Address of buffer for error information
00043  * RETURNS:
00044  *     Created socket, or INVALID_SOCKET if it could not be created
00045  */
00046 SOCKET
00047 WSPAPI
00048 WSPSocket(int AddressFamily,
00049           int SocketType,
00050           int Protocol,
00051           LPWSAPROTOCOL_INFOW lpProtocolInfo,
00052           GROUP g,
00053           DWORD dwFlags,
00054           LPINT lpErrno)
00055 {
00056     OBJECT_ATTRIBUTES           Object;
00057     IO_STATUS_BLOCK             IOSB;
00058     USHORT                      SizeOfPacket;
00059     ULONG                       SizeOfEA;
00060     PAFD_CREATE_PACKET          AfdPacket;
00061     HANDLE                      Sock;
00062     PSOCKET_INFORMATION         Socket = NULL;
00063     PFILE_FULL_EA_INFORMATION   EABuffer = NULL;
00064     PHELPER_DATA                HelperData;
00065     PVOID                       HelperDLLContext;
00066     DWORD                       HelperEvents;
00067     UNICODE_STRING              TransportName;
00068     UNICODE_STRING              DevName;
00069     LARGE_INTEGER               GroupData;
00070     INT                         Status;
00071 
00072     AFD_DbgPrint(MAX_TRACE, ("Creating Socket, getting TDI Name\n"));
00073     AFD_DbgPrint(MAX_TRACE, ("AddressFamily (%d)  SocketType (%d)  Protocol (%d).\n",
00074                              AddressFamily, SocketType, Protocol));
00075 
00076     /* Get Helper Data and Transport */
00077     Status = SockGetTdiName (&AddressFamily,
00078                              &SocketType,
00079                              &Protocol,
00080                              g,
00081                              dwFlags,
00082                              &TransportName,
00083                              &HelperDLLContext,
00084                              &HelperData,
00085                              &HelperEvents);
00086 
00087     /* Check for error */
00088     if (Status != NO_ERROR)
00089     {
00090         AFD_DbgPrint(MID_TRACE,("SockGetTdiName: Status %x\n", Status));
00091         goto error;
00092     }
00093 
00094     /* AFD Device Name */
00095     RtlInitUnicodeString(&DevName, L"\\Device\\Afd\\Endpoint");
00096 
00097     /* Set Socket Data */
00098     Socket = HeapAlloc(GlobalHeap, 0, sizeof(*Socket));
00099     if (!Socket)
00100         return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL);
00101 
00102     RtlZeroMemory(Socket, sizeof(*Socket));
00103     Socket->RefCount = 2;
00104     Socket->Handle = -1;
00105     Socket->SharedData.Listening = FALSE;
00106     Socket->SharedData.State = SocketOpen;
00107     Socket->SharedData.AddressFamily = AddressFamily;
00108     Socket->SharedData.SocketType = SocketType;
00109     Socket->SharedData.Protocol = Protocol;
00110     Socket->HelperContext = HelperDLLContext;
00111     Socket->HelperData = HelperData;
00112     Socket->HelperEvents = HelperEvents;
00113     Socket->LocalAddress = &Socket->WSLocalAddress;
00114     Socket->SharedData.SizeOfLocalAddress = HelperData->MaxWSAddressLength;
00115     Socket->RemoteAddress = &Socket->WSRemoteAddress;
00116     Socket->SharedData.SizeOfRemoteAddress = HelperData->MaxWSAddressLength;
00117     Socket->SharedData.UseDelayedAcceptance = HelperData->UseDelayedAcceptance;
00118     Socket->SharedData.CreateFlags = dwFlags;
00119     Socket->SharedData.CatalogEntryId = lpProtocolInfo->dwCatalogEntryId;
00120     Socket->SharedData.ServiceFlags1 = lpProtocolInfo->dwServiceFlags1;
00121     Socket->SharedData.ProviderFlags = lpProtocolInfo->dwProviderFlags;
00122     Socket->SharedData.GroupID = g;
00123     Socket->SharedData.GroupType = 0;
00124     Socket->SharedData.UseSAN = FALSE;
00125     Socket->SharedData.NonBlocking = FALSE; /* Sockets start blocking */
00126     Socket->SanData = NULL;
00127 
00128     /* Ask alex about this */
00129     if( Socket->SharedData.SocketType == SOCK_DGRAM ||
00130         Socket->SharedData.SocketType == SOCK_RAW )
00131     {
00132         AFD_DbgPrint(MID_TRACE,("Connectionless socket\n"));
00133         Socket->SharedData.ServiceFlags1 |= XP1_CONNECTIONLESS;
00134     }
00135 
00136     /* Packet Size */
00137     SizeOfPacket = TransportName.Length + sizeof(AFD_CREATE_PACKET) + sizeof(WCHAR);
00138 
00139     /* EA Size */
00140     SizeOfEA = SizeOfPacket + sizeof(FILE_FULL_EA_INFORMATION) + AFD_PACKET_COMMAND_LENGTH;
00141 
00142     /* Set up EA Buffer */
00143     EABuffer = HeapAlloc(GlobalHeap, 0, SizeOfEA);
00144     if (!EABuffer)
00145         return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL);
00146 
00147     RtlZeroMemory(EABuffer, SizeOfEA);
00148     EABuffer->NextEntryOffset = 0;
00149     EABuffer->Flags = 0;
00150     EABuffer->EaNameLength = AFD_PACKET_COMMAND_LENGTH;
00151     RtlCopyMemory (EABuffer->EaName,
00152                    AfdCommand,
00153                    AFD_PACKET_COMMAND_LENGTH + 1);
00154     EABuffer->EaValueLength = SizeOfPacket;
00155 
00156     /* Set up AFD Packet */
00157     AfdPacket = (PAFD_CREATE_PACKET)(EABuffer->EaName + EABuffer->EaNameLength + 1);
00158     AfdPacket->SizeOfTransportName = TransportName.Length;
00159     RtlCopyMemory (AfdPacket->TransportName,
00160                    TransportName.Buffer,
00161                    TransportName.Length + sizeof(WCHAR));
00162     AfdPacket->GroupID = g;
00163 
00164     /* Set up Endpoint Flags */
00165     if ((Socket->SharedData.ServiceFlags1 & XP1_CONNECTIONLESS) != 0)
00166     {
00167         if ((SocketType != SOCK_DGRAM) && (SocketType != SOCK_RAW))
00168         {
00169             /* Only RAW or UDP can be Connectionless */
00170             goto error;
00171         }
00172         AfdPacket->EndpointFlags |= AFD_ENDPOINT_CONNECTIONLESS;
00173     }
00174 
00175     if ((Socket->SharedData.ServiceFlags1 & XP1_MESSAGE_ORIENTED) != 0)
00176     {
00177         if (SocketType == SOCK_STREAM)
00178         {
00179             if ((Socket->SharedData.ServiceFlags1 & XP1_PSEUDO_STREAM) == 0)
00180             {
00181                 /* The Provider doesn't actually support Message Oriented Streams */
00182                 goto error;
00183             }
00184         }
00185         AfdPacket->EndpointFlags |= AFD_ENDPOINT_MESSAGE_ORIENTED;
00186     }
00187 
00188     if (SocketType == SOCK_RAW) AfdPacket->EndpointFlags |= AFD_ENDPOINT_RAW;
00189 
00190     if (dwFlags & (WSA_FLAG_MULTIPOINT_C_ROOT |
00191                    WSA_FLAG_MULTIPOINT_C_LEAF |
00192                    WSA_FLAG_MULTIPOINT_D_ROOT |
00193                    WSA_FLAG_MULTIPOINT_D_LEAF))
00194     {
00195         if ((Socket->SharedData.ServiceFlags1 & XP1_SUPPORT_MULTIPOINT) == 0)
00196         {
00197             /* The Provider doesn't actually support Multipoint */
00198             goto error;
00199         }
00200         AfdPacket->EndpointFlags |= AFD_ENDPOINT_MULTIPOINT;
00201 
00202         if (dwFlags & WSA_FLAG_MULTIPOINT_C_ROOT)
00203         {
00204             if (((Socket->SharedData.ServiceFlags1 & XP1_MULTIPOINT_CONTROL_PLANE) == 0)
00205                 || ((dwFlags & WSA_FLAG_MULTIPOINT_C_LEAF) != 0))
00206             {
00207                 /* The Provider doesn't support Control Planes, or you already gave a leaf */
00208                 goto error;
00209             }
00210             AfdPacket->EndpointFlags |= AFD_ENDPOINT_C_ROOT;
00211         }
00212 
00213         if (dwFlags & WSA_FLAG_MULTIPOINT_D_ROOT)
00214         {
00215             if (((Socket->SharedData.ServiceFlags1 & XP1_MULTIPOINT_DATA_PLANE) == 0)
00216                 || ((dwFlags & WSA_FLAG_MULTIPOINT_D_LEAF) != 0))
00217             {
00218                 /* The Provider doesn't support Data Planes, or you already gave a leaf */
00219                 goto error;
00220             }
00221             AfdPacket->EndpointFlags |= AFD_ENDPOINT_D_ROOT;
00222         }
00223     }
00224 
00225     /* Set up Object Attributes */
00226     InitializeObjectAttributes (&Object,
00227                                 &DevName,
00228                                 OBJ_CASE_INSENSITIVE | OBJ_INHERIT,
00229                                 0,
00230                                 0);
00231 
00232     /* Create the Socket as asynchronous. That means we have to block
00233     ourselves after every call to NtDeviceIoControlFile. This is
00234     because the kernel doesn't support overlapping synchronous I/O
00235     requests (made from multiple threads) at this time (Sep 2005) */
00236     Status = NtCreateFile(&Sock,
00237                           GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
00238                           &Object,
00239                           &IOSB,
00240                           NULL,
00241                           0,
00242                           FILE_SHARE_READ | FILE_SHARE_WRITE,
00243                           FILE_OPEN_IF,
00244                           0,
00245                           EABuffer,
00246                           SizeOfEA);
00247 
00248     HeapFree(GlobalHeap, 0, EABuffer);
00249 
00250     if (Status != STATUS_SUCCESS)
00251     {
00252         AFD_DbgPrint(MIN_TRACE, ("Failed to open socket\n"));
00253 
00254         HeapFree(GlobalHeap, 0, Socket);
00255 
00256         return MsafdReturnWithErrno(Status, lpErrno, 0, NULL);
00257     }
00258 
00259     /* Save Handle */
00260     Socket->Handle = (SOCKET)Sock;
00261 
00262     /* Save Group Info */
00263     if (g != 0)
00264     {
00265         GetSocketInformation(Socket, AFD_INFO_GROUP_ID_TYPE, NULL, NULL, &GroupData);
00266         Socket->SharedData.GroupID = GroupData.u.LowPart;
00267         Socket->SharedData.GroupType = GroupData.u.HighPart;
00268     }
00269 
00270     /* Get Window Sizes and Save them */
00271     GetSocketInformation (Socket,
00272                           AFD_INFO_SEND_WINDOW_SIZE,
00273                           NULL,
00274                           &Socket->SharedData.SizeOfSendBuffer,
00275                           NULL);
00276 
00277     GetSocketInformation (Socket,
00278                           AFD_INFO_RECEIVE_WINDOW_SIZE,
00279                           NULL,
00280                           &Socket->SharedData.SizeOfRecvBuffer,
00281                           NULL);
00282 
00283     /* Save in Process Sockets List */
00284     EnterCriticalSection(&SocketListLock);
00285     Socket->NextSocket = SocketListHead;
00286     SocketListHead = Socket;
00287     LeaveCriticalSection(&SocketListLock);
00288 
00289     /* Create the Socket Context */
00290     CreateContext(Socket);
00291 
00292     /* Notify Winsock */
00293     Upcalls.lpWPUModifyIFSHandle(1, (SOCKET)Sock, lpErrno);
00294 
00295     /* Return Socket Handle */
00296     AFD_DbgPrint(MID_TRACE,("Success %x\n", Sock));
00297 
00298     return (SOCKET)Sock;
00299 
00300 error:
00301     AFD_DbgPrint(MID_TRACE,("Ending %x\n", Status));
00302 
00303     if( Socket )
00304         HeapFree(GlobalHeap, 0, Socket);
00305 
00306     if( lpErrno )
00307         *lpErrno = Status;
00308 
00309     return INVALID_SOCKET;
00310 }
00311 
00312 INT
00313 TranslateNtStatusError(NTSTATUS Status)
00314 {
00315     switch (Status)
00316     {
00317        case STATUS_CANT_WAIT:
00318           return WSAEWOULDBLOCK;
00319 
00320        case STATUS_TIMEOUT:
00321           return WSAETIMEDOUT;
00322 
00323        case STATUS_SUCCESS:
00324           return NO_ERROR;
00325 
00326        case STATUS_FILE_CLOSED:
00327        case STATUS_END_OF_FILE:
00328           return WSAESHUTDOWN;
00329 
00330        case STATUS_PENDING:
00331           return WSA_IO_PENDING;
00332 
00333        case STATUS_BUFFER_TOO_SMALL:
00334        case STATUS_BUFFER_OVERFLOW:
00335           DbgPrint("MSAFD: STATUS_BUFFER_TOO_SMALL/STATUS_BUFFER_OVERFLOW\n");
00336           return WSAEMSGSIZE;
00337 
00338        case STATUS_NO_MEMORY:
00339        case STATUS_INSUFFICIENT_RESOURCES:
00340           DbgPrint("MSAFD: STATUS_NO_MEMORY/STATUS_INSUFFICIENT_RESOURCES\n");
00341           return WSAENOBUFS;
00342 
00343        case STATUS_INVALID_CONNECTION:
00344           DbgPrint("MSAFD: STATUS_INVALID_CONNECTION\n");
00345           return WSAEAFNOSUPPORT;
00346 
00347        case STATUS_INVALID_ADDRESS:
00348           DbgPrint("MSAFD: STATUS_INVALID_ADDRESS\n");
00349           return WSAEADDRNOTAVAIL;
00350 
00351        case STATUS_REMOTE_NOT_LISTENING:
00352           DbgPrint("MSAFD: STATUS_REMOTE_NOT_LISTENING\n");
00353           return WSAECONNREFUSED;
00354 
00355        case STATUS_NETWORK_UNREACHABLE:
00356           DbgPrint("MSAFD: STATUS_NETWORK_UNREACHABLE\n");
00357           return WSAENETUNREACH;
00358 
00359        case STATUS_INVALID_PARAMETER:
00360           DbgPrint("MSAFD: STATUS_INVALID_PARAMETER\n");
00361           return WSAEINVAL;
00362 
00363        case STATUS_CANCELLED:
00364           DbgPrint("MSAFD: STATUS_CANCELLED\n");
00365           return WSA_OPERATION_ABORTED;
00366 
00367        case STATUS_ADDRESS_ALREADY_EXISTS:
00368           DbgPrint("MSAFD: STATUS_ADDRESS_ALREADY_EXISTS\n");
00369           return WSAEADDRINUSE;
00370 
00371        case STATUS_LOCAL_DISCONNECT:
00372           DbgPrint("MSAFD: STATUS_LOCAL_DISCONNECT\n");
00373           return WSAECONNABORTED;
00374 
00375        case STATUS_REMOTE_DISCONNECT:
00376           DbgPrint("MSAFD: STATUS_REMOTE_DISCONNECT\n");
00377           return WSAECONNRESET;
00378 
00379        default:
00380           DbgPrint("MSAFD: Unhandled NTSTATUS value: 0x%x\n", Status);
00381           return WSAENETDOWN;
00382     }
00383 }
00384 
00385 /*
00386  * FUNCTION: Closes an open socket
00387  * ARGUMENTS:
00388  *     s       = Socket descriptor
00389  *     lpErrno = Address of buffer for error information
00390  * RETURNS:
00391  *     NO_ERROR, or SOCKET_ERROR if the socket could not be closed
00392  */
00393 INT
00394 WSPAPI
00395 WSPCloseSocket(IN SOCKET Handle,
00396                OUT LPINT lpErrno)
00397 {
00398     IO_STATUS_BLOCK IoStatusBlock;
00399     PSOCKET_INFORMATION Socket = NULL, CurrentSocket;
00400     NTSTATUS Status;
00401     HANDLE SockEvent;
00402     AFD_DISCONNECT_INFO DisconnectInfo;
00403     SOCKET_STATE OldState;
00404     LONG LingerWait = -1;
00405 
00406     /* Create the Wait Event */
00407     Status = NtCreateEvent(&SockEvent,
00408                            GENERIC_READ | GENERIC_WRITE,
00409                            NULL,
00410                            1,
00411                            FALSE);
00412 
00413     if(!NT_SUCCESS(Status))
00414         return SOCKET_ERROR;
00415 
00416     /* Get the Socket Structure associate to this Socket*/
00417     Socket = GetSocketStructure(Handle);
00418     if (!Socket)
00419     {
00420        NtClose(SockEvent);
00421        *lpErrno = WSAENOTSOCK;
00422        return SOCKET_ERROR;
00423     }
00424 
00425     if (Socket->HelperEvents & WSH_NOTIFY_CLOSE)
00426     {
00427         Status = Socket->HelperData->WSHNotify(Socket->HelperContext,
00428                                                Socket->Handle,
00429                                                Socket->TdiAddressHandle,
00430                                                Socket->TdiConnectionHandle,
00431                                                WSH_NOTIFY_CLOSE);
00432 
00433         if (Status)
00434         {
00435             if (lpErrno) *lpErrno = Status;
00436             NtClose(SockEvent);
00437             return SOCKET_ERROR;
00438         }
00439     }
00440 
00441     /* If a Close is already in Process, give up */
00442     if (Socket->SharedData.State == SocketClosed)
00443     {
00444         NtClose(SockEvent);
00445         *lpErrno = WSAENOTSOCK;
00446         return SOCKET_ERROR;
00447     }
00448 
00449     /* Set the state to close */
00450     OldState = Socket->SharedData.State;
00451     Socket->SharedData.State = SocketClosed;
00452 
00453     /* If SO_LINGER is ON and the Socket is connected, we need to disconnect */
00454     /* FIXME: Should we do this on Datagram Sockets too? */
00455     if ((OldState == SocketConnected) && (Socket->SharedData.LingerData.l_onoff))
00456     {
00457         ULONG SendsInProgress;
00458         ULONG SleepWait;
00459 
00460         /* We need to respect the timeout */
00461         SleepWait = 100;
00462         LingerWait = Socket->SharedData.LingerData.l_linger * 1000;
00463 
00464         /* Loop until no more sends are pending, within the timeout */
00465         while (LingerWait)
00466         {
00467             /* Find out how many Sends are in Progress */
00468             if (GetSocketInformation(Socket,
00469                                      AFD_INFO_SENDS_IN_PROGRESS,
00470                                      NULL,
00471                                      &SendsInProgress,
00472                                      NULL))
00473             {
00474                 /* Bail out if anything but NO_ERROR */
00475                 LingerWait = 0;
00476                 break;
00477             }
00478 
00479             /* Bail out if no more sends are pending */
00480             if (!SendsInProgress)
00481             {
00482                 LingerWait = -1;
00483                 break;
00484             }
00485 
00486             /*
00487              * We have to execute a sleep, so it's kind of like
00488              * a block. If the socket is Nonblock, we cannot
00489              * go on since asyncronous operation is expected
00490              * and we cannot offer it
00491              */
00492             if (Socket->SharedData.NonBlocking)
00493             {
00494                 NtClose(SockEvent);
00495                 Socket->SharedData.State = OldState;
00496                 *lpErrno = WSAEWOULDBLOCK;
00497                 return SOCKET_ERROR;
00498             }
00499 
00500             /* Now we can sleep, and decrement the linger wait */
00501             /*
00502             * FIXME: It seems Windows does some funky acceleration
00503             * since the waiting seems to be longer and longer. I
00504             * don't think this improves performance so much, so we
00505             * wait a fixed time instead.
00506             */
00507             Sleep(SleepWait);
00508             LingerWait -= SleepWait;
00509         }
00510     }
00511 
00512     if (OldState == SocketConnected)
00513     {
00514         if (LingerWait <= 0)
00515         {
00516             DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(0);
00517             DisconnectInfo.DisconnectType = LingerWait < 0 ? AFD_DISCONNECT_SEND : AFD_DISCONNECT_ABORT;
00518 
00519             if (((DisconnectInfo.DisconnectType & AFD_DISCONNECT_SEND) && (!Socket->SharedData.SendShutdown)) ||
00520                 ((DisconnectInfo.DisconnectType & AFD_DISCONNECT_ABORT) && (!Socket->SharedData.ReceiveShutdown)))
00521             {
00522                 /* Send IOCTL */
00523                 Status = NtDeviceIoControlFile((HANDLE)Handle,
00524                                                SockEvent,
00525                                                NULL,
00526                                                NULL,
00527                                                &IoStatusBlock,
00528                                                IOCTL_AFD_DISCONNECT,
00529                                                &DisconnectInfo,
00530                                                sizeof(DisconnectInfo),
00531                                                NULL,
00532                                                0);
00533 
00534                 /* Wait for return */
00535                 if (Status == STATUS_PENDING)
00536                 {
00537                     WaitForSingleObject(SockEvent, INFINITE);
00538                     Status = IoStatusBlock.Status;
00539                 }
00540             }
00541         }
00542     }
00543 
00544     /* Cleanup Time! */
00545     Socket->HelperContext = NULL;
00546     Socket->SharedData.AsyncDisabledEvents = -1;
00547     NtClose(Socket->TdiAddressHandle);
00548     Socket->TdiAddressHandle = NULL;
00549     NtClose(Socket->TdiConnectionHandle);
00550     Socket->TdiConnectionHandle = NULL;
00551 
00552     EnterCriticalSection(&SocketListLock);
00553     if (SocketListHead == Socket)
00554     {
00555         SocketListHead = SocketListHead->NextSocket;
00556     }
00557     else
00558     {
00559         CurrentSocket = SocketListHead;
00560         while (CurrentSocket->NextSocket)
00561         {
00562             if (CurrentSocket->NextSocket == Socket)
00563             {
00564                 CurrentSocket->NextSocket = CurrentSocket->NextSocket->NextSocket;
00565                 break;
00566             }
00567 
00568             CurrentSocket = CurrentSocket->NextSocket;
00569         }
00570     }
00571     LeaveCriticalSection(&SocketListLock);
00572 
00573     /* Close the handle */
00574     NtClose((HANDLE)Handle);
00575     NtClose(SockEvent);
00576 
00577     HeapFree(GlobalHeap, 0, Socket);
00578     return MsafdReturnWithErrno(Status, lpErrno, 0, NULL);
00579 }
00580 
00581 
00582 /*
00583  * FUNCTION: Associates a local address with a socket
00584  * ARGUMENTS:
00585  *     s       = Socket descriptor
00586  *     name    = Pointer to local address
00587  *     namelen = Length of name
00588  *     lpErrno = Address of buffer for error information
00589  * RETURNS:
00590  *     0, or SOCKET_ERROR if the socket could not be bound
00591  */
00592 INT
00593 WSPAPI
00594 WSPBind(SOCKET Handle,
00595         const struct sockaddr *SocketAddress,
00596         int SocketAddressLength,
00597         LPINT lpErrno)
00598 {
00599     IO_STATUS_BLOCK         IOSB;
00600     PAFD_BIND_DATA          BindData;
00601     PSOCKET_INFORMATION     Socket = NULL;
00602     NTSTATUS                Status;
00603     SOCKADDR_INFO           SocketInfo;
00604     HANDLE                  SockEvent;
00605 
00606     /* See below */
00607     BindData = HeapAlloc(GlobalHeap, 0, 0xA + SocketAddressLength);
00608     if (!BindData)
00609     {
00610         return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL);
00611     }
00612 
00613     Status = NtCreateEvent(&SockEvent,
00614                            GENERIC_READ | GENERIC_WRITE,
00615                            NULL,
00616                            1,
00617                            FALSE);
00618 
00619     if (!NT_SUCCESS(Status))
00620     {
00621         HeapFree(GlobalHeap, 0, BindData);
00622         return SOCKET_ERROR;
00623     }
00624 
00625     /* Get the Socket Structure associate to this Socket*/
00626     Socket = GetSocketStructure(Handle);
00627     if (!Socket)
00628     {
00629        HeapFree(GlobalHeap, 0, BindData);
00630        *lpErrno = WSAENOTSOCK;
00631        return SOCKET_ERROR;
00632     }
00633 
00634     /* Set up Address in TDI Format */
00635     BindData->Address.TAAddressCount = 1;
00636     BindData->Address.Address[0].AddressLength = SocketAddressLength - sizeof(SocketAddress->sa_family);
00637     BindData->Address.Address[0].AddressType = SocketAddress->sa_family;
00638     RtlCopyMemory (BindData->Address.Address[0].Address,
00639                    SocketAddress->sa_data,
00640                    SocketAddressLength - sizeof(SocketAddress->sa_family));
00641 
00642     /* Get Address Information */
00643     Socket->HelperData->WSHGetSockaddrType ((PSOCKADDR)SocketAddress,
00644                                             SocketAddressLength,
00645                                             &SocketInfo);
00646 
00647     /* Set the Share Type */
00648     if (Socket->SharedData.ExclusiveAddressUse)
00649     {
00650         BindData->ShareType = AFD_SHARE_EXCLUSIVE;
00651     }
00652     else if (SocketInfo.EndpointInfo == SockaddrEndpointInfoWildcard)
00653     {
00654         BindData->ShareType = AFD_SHARE_WILDCARD;
00655     }
00656     else if (Socket->SharedData.ReuseAddresses)
00657     {
00658         BindData->ShareType = AFD_SHARE_REUSE;
00659     }
00660     else
00661     {
00662         BindData->ShareType = AFD_SHARE_UNIQUE;
00663     }
00664 
00665     /* Send IOCTL */
00666     Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
00667                                    SockEvent,
00668                                    NULL,
00669                                    NULL,
00670                                    &IOSB,
00671                                    IOCTL_AFD_BIND,
00672                                    BindData,
00673                                    0xA + Socket->SharedData.SizeOfLocalAddress, /* Can't figure out a way to calculate this in C*/
00674                                    BindData,
00675                                    0xA + Socket->SharedData.SizeOfLocalAddress); /* Can't figure out a way to calculate this C */
00676 
00677     /* Wait for return */
00678     if (Status == STATUS_PENDING)
00679     {
00680         WaitForSingleObject(SockEvent, INFINITE);
00681         Status = IOSB.Status;
00682     }
00683 
00684     NtClose( SockEvent );
00685     HeapFree(GlobalHeap, 0, BindData);
00686 
00687     if (Status != STATUS_SUCCESS)
00688         return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL );
00689 
00690     /* Set up Socket Data */
00691     Socket->SharedData.State = SocketBound;
00692     Socket->TdiAddressHandle = (HANDLE)IOSB.Information;
00693 
00694     if (Socket->HelperEvents & WSH_NOTIFY_BIND)
00695     {
00696         Status = Socket->HelperData->WSHNotify(Socket->HelperContext,
00697                                                Socket->Handle,
00698                                                Socket->TdiAddressHandle,
00699                                                Socket->TdiConnectionHandle,
00700                                                WSH_NOTIFY_BIND);
00701 
00702         if (Status)
00703         {
00704             if (lpErrno) *lpErrno = Status;
00705             return SOCKET_ERROR;
00706         }
00707     }
00708 
00709     return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL );
00710 }
00711 
00712 int
00713 WSPAPI
00714 WSPListen(SOCKET Handle,
00715           int Backlog,
00716           LPINT lpErrno)
00717 {
00718     IO_STATUS_BLOCK         IOSB;
00719     AFD_LISTEN_DATA         ListenData;
00720     PSOCKET_INFORMATION     Socket = NULL;
00721     HANDLE                  SockEvent;
00722     NTSTATUS                Status;
00723 
00724     /* Get the Socket Structure associate to this Socket*/
00725     Socket = GetSocketStructure(Handle);
00726     if (!Socket)
00727     {
00728        *lpErrno = WSAENOTSOCK;
00729        return SOCKET_ERROR;
00730     }
00731 
00732     if (Socket->SharedData.Listening)
00733         return 0;
00734 
00735     Status = NtCreateEvent(&SockEvent,
00736                            GENERIC_READ | GENERIC_WRITE,
00737                            NULL,
00738                            1,
00739                            FALSE);
00740 
00741     if( !NT_SUCCESS(Status) )
00742         return -1;
00743 
00744     /* Set Up Listen Structure */
00745     ListenData.UseSAN = FALSE;
00746     ListenData.UseDelayedAcceptance = Socket->SharedData.UseDelayedAcceptance;
00747     ListenData.Backlog = Backlog;
00748 
00749     /* Send IOCTL */
00750     Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
00751                                    SockEvent,
00752                                    NULL,
00753                                    NULL,
00754                                    &IOSB,
00755                                    IOCTL_AFD_START_LISTEN,
00756                                    &ListenData,
00757                                    sizeof(ListenData),
00758                                    NULL,
00759                                    0);
00760 
00761     /* Wait for return */
00762     if (Status == STATUS_PENDING)
00763     {
00764         WaitForSingleObject(SockEvent, INFINITE);
00765         Status = IOSB.Status;
00766     }
00767 
00768     NtClose( SockEvent );
00769 
00770     if (Status != STATUS_SUCCESS)
00771        return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL );
00772 
00773     /* Set to Listening */
00774     Socket->SharedData.Listening = TRUE;
00775 
00776     if (Socket->HelperEvents & WSH_NOTIFY_LISTEN)
00777     {
00778         Status = Socket->HelperData->WSHNotify(Socket->HelperContext,
00779                                                Socket->Handle,
00780                                                Socket->TdiAddressHandle,
00781                                                Socket->TdiConnectionHandle,
00782                                                WSH_NOTIFY_LISTEN);
00783 
00784         if (Status)
00785         {
00786            if (lpErrno) *lpErrno = Status;
00787            return SOCKET_ERROR;
00788         }
00789     }
00790 
00791     return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL );
00792 }
00793 
00794 
00795 int
00796 WSPAPI
00797 WSPSelect(IN int nfds,
00798           IN OUT fd_set *readfds OPTIONAL,
00799           IN OUT fd_set *writefds OPTIONAL,
00800           IN OUT fd_set *exceptfds OPTIONAL,
00801           IN const struct timeval *timeout OPTIONAL,
00802           OUT LPINT lpErrno)
00803 {
00804     IO_STATUS_BLOCK     IOSB;
00805     PAFD_POLL_INFO      PollInfo;
00806     NTSTATUS            Status;
00807     ULONG               HandleCount;
00808     LONG                OutCount = 0;
00809     ULONG               PollBufferSize;
00810     PVOID               PollBuffer;
00811     ULONG               i, j = 0, x;
00812     HANDLE              SockEvent;
00813     BOOL                HandleCounted;
00814     LARGE_INTEGER       Timeout;
00815 
00816     /* Find out how many sockets we have, and how large the buffer needs
00817      * to be */
00818 
00819     HandleCount = ( readfds ? readfds->fd_count : 0 ) +
00820                   ( writefds ? writefds->fd_count : 0 ) +
00821                   ( exceptfds ? exceptfds->fd_count : 0 );
00822 
00823     if ( HandleCount == 0 )
00824     {
00825         AFD_DbgPrint(MAX_TRACE,("HandleCount: %u. Return SOCKET_ERROR\n",
00826                      HandleCount));
00827         if (lpErrno) *lpErrno = WSAEINVAL;
00828         return SOCKET_ERROR;
00829     }
00830 
00831     PollBufferSize = sizeof(*PollInfo) + ((HandleCount - 1) * sizeof(AFD_HANDLE));
00832 
00833     AFD_DbgPrint(MID_TRACE,("HandleCount: %u BufferSize: %u\n",
00834                  HandleCount, PollBufferSize));
00835 
00836     /* Convert Timeout to NT Format */
00837     if (timeout == NULL)
00838     {
00839         Timeout.u.LowPart = -1;
00840         Timeout.u.HighPart = 0x7FFFFFFF;
00841         AFD_DbgPrint(MAX_TRACE,("Infinite timeout\n"));
00842     }
00843     else
00844     {
00845         Timeout = RtlEnlargedIntegerMultiply
00846             ((timeout->tv_sec * 1000) + (timeout->tv_usec / 1000), -10000);
00847         /* Negative timeouts are illegal.  Since the kernel represents an
00848          * incremental timeout as a negative number, we check for a positive
00849          * result.
00850          */
00851         if (Timeout.QuadPart > 0)
00852         {
00853             if (lpErrno) *lpErrno = WSAEINVAL;
00854                 return SOCKET_ERROR;
00855         }
00856         AFD_DbgPrint(MAX_TRACE,("Timeout: Orig %d.%06d kernel %d\n",
00857                      timeout->tv_sec, timeout->tv_usec,
00858                      Timeout.u.LowPart));
00859     }
00860 
00861     Status = NtCreateEvent(&SockEvent,
00862                            GENERIC_READ | GENERIC_WRITE,
00863                            NULL,
00864                            1,
00865                            FALSE);
00866 
00867     if( !NT_SUCCESS(Status) )
00868         return SOCKET_ERROR;
00869 
00870     /* Allocate */
00871     PollBuffer = HeapAlloc(GlobalHeap, 0, PollBufferSize);
00872 
00873     if (!PollBuffer)
00874     {
00875         if (lpErrno)
00876             *lpErrno = WSAEFAULT;
00877         NtClose(SockEvent);
00878         return SOCKET_ERROR;
00879     }
00880 
00881     PollInfo = (PAFD_POLL_INFO)PollBuffer;
00882 
00883     RtlZeroMemory( PollInfo, PollBufferSize );
00884 
00885     /* Number of handles for AFD to Check */
00886     PollInfo->Exclusive = FALSE;
00887     PollInfo->Timeout = Timeout;
00888 
00889     if (readfds != NULL) {
00890         for (i = 0; i < readfds->fd_count; i++, j++)
00891         {
00892             PollInfo->Handles[j].Handle = readfds->fd_array[i];
00893             PollInfo->Handles[j].Events = AFD_EVENT_RECEIVE |
00894                                           AFD_EVENT_DISCONNECT |
00895                                           AFD_EVENT_ABORT |
00896                                           AFD_EVENT_CLOSE |
00897                                           AFD_EVENT_ACCEPT;
00898         }
00899     }
00900     if (writefds != NULL)
00901     {
00902         for (i = 0; i < writefds->fd_count; i++, j++)
00903         {
00904             PollInfo->Handles[j].Handle = writefds->fd_array[i];
00905             PollInfo->Handles[j].Events = AFD_EVENT_SEND | AFD_EVENT_CONNECT;
00906         }
00907     }
00908     if (exceptfds != NULL)
00909     {
00910         for (i = 0; i < exceptfds->fd_count; i++, j++)
00911         {
00912             PollInfo->Handles[j].Handle = exceptfds->fd_array[i];
00913             PollInfo->Handles[j].Events = AFD_EVENT_OOB_RECEIVE | AFD_EVENT_CONNECT_FAIL;
00914         }
00915     }
00916 
00917     PollInfo->HandleCount = j;
00918     PollBufferSize = FIELD_OFFSET(AFD_POLL_INFO, Handles) + PollInfo->HandleCount * sizeof(AFD_HANDLE);
00919 
00920     /* Send IOCTL */
00921     Status = NtDeviceIoControlFile((HANDLE)PollInfo->Handles[0].Handle,
00922                                    SockEvent,
00923                                    NULL,
00924                                    NULL,
00925                                    &IOSB,
00926                                    IOCTL_AFD_SELECT,
00927                                    PollInfo,
00928                                    PollBufferSize,
00929                                    PollInfo,
00930                                    PollBufferSize);
00931 
00932     AFD_DbgPrint(MID_TRACE,("DeviceIoControlFile => %x\n", Status));
00933 
00934     /* Wait for Completition */
00935     if (Status == STATUS_PENDING)
00936     {
00937         WaitForSingleObject(SockEvent, INFINITE);
00938         Status = IOSB.Status;
00939     }
00940 
00941     /* Clear the Structures */
00942     if( readfds )
00943         FD_ZERO(readfds);
00944     if( writefds )
00945         FD_ZERO(writefds);
00946     if( exceptfds )
00947         FD_ZERO(exceptfds);
00948 
00949     /* Loop through return structure */
00950     HandleCount = PollInfo->HandleCount;
00951 
00952     /* Return in FDSET Format */
00953     for (i = 0; i < HandleCount; i++)
00954     {
00955         HandleCounted = FALSE;
00956         for(x = 1; x; x<<=1)
00957         {
00958             switch (PollInfo->Handles[i].Events & x)
00959             {
00960                 case AFD_EVENT_RECEIVE:
00961                 case AFD_EVENT_DISCONNECT:
00962                 case AFD_EVENT_ABORT:
00963                 case AFD_EVENT_ACCEPT:
00964                 case AFD_EVENT_CLOSE:
00965                     AFD_DbgPrint(MID_TRACE,("Event %x on handle %x\n",
00966                                  PollInfo->Handles[i].Events,
00967                                  PollInfo->Handles[i].Handle));
00968                     if (! HandleCounted)
00969                     {
00970                         OutCount++;
00971                         HandleCounted = TRUE;
00972                     }
00973                     if( readfds )
00974                         FD_SET(PollInfo->Handles[i].Handle, readfds);
00975                     break;
00976                 case AFD_EVENT_SEND:
00977                 case AFD_EVENT_CONNECT:
00978                     AFD_DbgPrint(MID_TRACE,("Event %x on handle %x\n",
00979                                  PollInfo->Handles[i].Events,
00980                                  PollInfo->Handles[i].Handle));
00981                     if (! HandleCounted)
00982                     {
00983                         OutCount++;
00984                         HandleCounted = TRUE;
00985                     }
00986                     if( writefds )
00987                         FD_SET(PollInfo->Handles[i].Handle, writefds);
00988                     break;
00989                 case AFD_EVENT_OOB_RECEIVE:
00990                 case AFD_EVENT_CONNECT_FAIL:
00991                     AFD_DbgPrint(MID_TRACE,("Event %x on handle %x\n",
00992                                  PollInfo->Handles[i].Events,
00993                                  PollInfo->Handles[i].Handle));
00994                     if (! HandleCounted)
00995                     {
00996                         OutCount++;
00997                         HandleCounted = TRUE;
00998                     }
00999                     if( exceptfds )
01000                         FD_SET(PollInfo->Handles[i].Handle, exceptfds);
01001                     break;
01002             }
01003         }
01004     }
01005 
01006     HeapFree( GlobalHeap, 0, PollBuffer );
01007     NtClose( SockEvent );
01008 
01009     if( lpErrno )
01010     {
01011         switch( IOSB.Status )
01012         {
01013             case STATUS_SUCCESS:
01014             case STATUS_TIMEOUT:
01015                 *lpErrno = 0;
01016                 break;
01017             default:
01018                 *lpErrno = WSAEINVAL;
01019                 break;
01020         }
01021         AFD_DbgPrint(MID_TRACE,("*lpErrno = %x\n", *lpErrno));
01022     }
01023 
01024     AFD_DbgPrint(MID_TRACE,("%d events\n", OutCount));
01025 
01026     return OutCount;
01027 }
01028 
01029 SOCKET
01030 WSPAPI
01031 WSPAccept(SOCKET Handle,
01032           struct sockaddr *SocketAddress,
01033           int *SocketAddressLength,
01034           LPCONDITIONPROC lpfnCondition,
01035           DWORD dwCallbackData,
01036           LPINT lpErrno)
01037 {
01038     IO_STATUS_BLOCK             IOSB;
01039     PAFD_RECEIVED_ACCEPT_DATA   ListenReceiveData;
01040     AFD_ACCEPT_DATA             AcceptData;
01041     AFD_DEFER_ACCEPT_DATA       DeferData;
01042     AFD_PENDING_ACCEPT_DATA     PendingAcceptData;
01043     PSOCKET_INFORMATION         Socket = NULL;
01044     NTSTATUS                    Status;
01045     struct fd_set               ReadSet;
01046     struct timeval              Timeout;
01047     PVOID                       PendingData = NULL;
01048     ULONG                       PendingDataLength = 0;
01049     PVOID                       CalleeDataBuffer;
01050     WSABUF                      CallerData, CalleeID, CallerID, CalleeData;
01051     PSOCKADDR                   RemoteAddress =  NULL;
01052     GROUP                       GroupID = 0;
01053     ULONG                       CallBack;
01054     WSAPROTOCOL_INFOW           ProtocolInfo;
01055     SOCKET                      AcceptSocket;
01056     PSOCKET_INFORMATION         AcceptSocketInfo;
01057     UCHAR                       ReceiveBuffer[0x1A];
01058     HANDLE                      SockEvent;
01059 
01060     Status = NtCreateEvent(&SockEvent,
01061                            GENERIC_READ | GENERIC_WRITE,
01062                            NULL,
01063                            1,
01064                            FALSE);
01065 
01066     if( !NT_SUCCESS(Status) )
01067     {
01068         MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
01069         return INVALID_SOCKET;
01070     }
01071 
01072     /* Dynamic Structure...ugh */
01073     ListenReceiveData = (PAFD_RECEIVED_ACCEPT_DATA)ReceiveBuffer;
01074 
01075     /* Get the Socket Structure associate to this Socket*/
01076     Socket = GetSocketStructure(Handle);
01077     if (!Socket)
01078     {
01079        NtClose(SockEvent);
01080        *lpErrno = WSAENOTSOCK;
01081        return INVALID_SOCKET;
01082     }
01083 
01084     /* If this is non-blocking, make sure there's something for us to accept */
01085     FD_ZERO(&ReadSet);
01086     FD_SET(Socket->Handle, &ReadSet);
01087     Timeout.tv_sec=0;
01088     Timeout.tv_usec=0;
01089 
01090     if (WSPSelect(0, &ReadSet, NULL, NULL, &Timeout, lpErrno) == SOCKET_ERROR)
01091     {
01092         NtClose(SockEvent);
01093         return INVALID_SOCKET;
01094     }
01095 
01096     if (ReadSet.fd_array[0] != Socket->Handle)
01097     {
01098         NtClose(SockEvent);
01099         *lpErrno = WSAEWOULDBLOCK;
01100         return INVALID_SOCKET;
01101     }
01102 
01103     /* Send IOCTL */
01104     Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
01105                                    SockEvent,
01106                                    NULL,
01107                                    NULL,
01108                                    &IOSB,
01109                                    IOCTL_AFD_WAIT_FOR_LISTEN,
01110                                    NULL,
01111                                    0,
01112                                    ListenReceiveData,
01113                                    0xA + sizeof(*ListenReceiveData));
01114 
01115     /* Wait for return */
01116     if (Status == STATUS_PENDING)
01117     {
01118         WaitForSingleObject(SockEvent, INFINITE);
01119         Status = IOSB.Status;
01120     }
01121 
01122     if (!NT_SUCCESS(Status))
01123     {
01124         NtClose( SockEvent );
01125         MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
01126         return INVALID_SOCKET;
01127     }
01128 
01129     if (lpfnCondition != NULL)
01130     {
01131         if ((Socket->SharedData.ServiceFlags1 & XP1_CONNECT_DATA) != 0)
01132         {
01133             /* Find out how much data is pending */
01134             PendingAcceptData.SequenceNumber = ListenReceiveData->SequenceNumber;
01135             PendingAcceptData.ReturnSize = TRUE;
01136 
01137             /* Send IOCTL */
01138             Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
01139                                            SockEvent,
01140                                            NULL,
01141                                            NULL,
01142                                            &IOSB,
01143                                            IOCTL_AFD_GET_PENDING_CONNECT_DATA,
01144                                            &PendingAcceptData,
01145                                            sizeof(PendingAcceptData),
01146                                            &PendingAcceptData,
01147                                            sizeof(PendingAcceptData));
01148 
01149             /* Wait for return */
01150             if (Status == STATUS_PENDING)
01151             {
01152                 WaitForSingleObject(SockEvent, INFINITE);
01153                 Status = IOSB.Status;
01154             }
01155 
01156             if (!NT_SUCCESS(Status))
01157             {
01158                 NtClose( SockEvent );
01159                 MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
01160                 return INVALID_SOCKET;
01161             }
01162 
01163             /* How much data to allocate */
01164             PendingDataLength = IOSB.Information;
01165 
01166             if (PendingDataLength)
01167             {
01168                 /* Allocate needed space */
01169                 PendingData = HeapAlloc(GlobalHeap, 0, PendingDataLength);
01170                 if (!PendingData)
01171                 {
01172                     MsafdReturnWithErrno( STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL );
01173                     return INVALID_SOCKET;
01174                 }
01175 
01176                 /* We want the data now */
01177                 PendingAcceptData.ReturnSize = FALSE;
01178 
01179                 /* Send IOCTL */
01180                 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
01181                                                SockEvent,
01182                                                NULL,
01183                                                NULL,
01184                                                &IOSB,
01185                                                IOCTL_AFD_GET_PENDING_CONNECT_DATA,
01186                                                &PendingAcceptData,
01187                                                sizeof(PendingAcceptData),
01188                                                PendingData,
01189                                                PendingDataLength);
01190 
01191                 /* Wait for return */
01192                 if (Status == STATUS_PENDING)
01193                 {
01194                     WaitForSingleObject(SockEvent, INFINITE);
01195                     Status = IOSB.Status;
01196                 }
01197 
01198                 if (!NT_SUCCESS(Status))
01199                 {
01200                     NtClose( SockEvent );
01201                     MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
01202                     return INVALID_SOCKET;
01203                 }
01204             }
01205         }
01206 
01207         if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED) != 0)
01208         {
01209             /* I don't support this yet */
01210         }
01211 
01212         /* Build Callee ID */
01213         CalleeID.buf = (PVOID)Socket->LocalAddress;
01214         CalleeID.len = Socket->SharedData.SizeOfLocalAddress;
01215 
01216         RemoteAddress = HeapAlloc(GlobalHeap, 0, sizeof(*RemoteAddress));
01217         if (!RemoteAddress)
01218         {
01219             MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL);
01220             return INVALID_SOCKET;
01221         }
01222 
01223         /* Set up Address in SOCKADDR Format */
01224         RtlCopyMemory (RemoteAddress,
01225                        &ListenReceiveData->Address.Address[0].AddressType,
01226                        sizeof(*RemoteAddress));
01227 
01228         /* Build Caller ID */
01229         CallerID.buf = (PVOID)RemoteAddress;
01230         CallerID.len = sizeof(*RemoteAddress);
01231 
01232         /* Build Caller Data */
01233         CallerData.buf = PendingData;
01234         CallerData.len = PendingDataLength;
01235 
01236         /* Check if socket supports Conditional Accept */
01237         if (Socket->SharedData.UseDelayedAcceptance != 0)
01238         {
01239             /* Allocate Buffer for Callee Data */
01240             CalleeDataBuffer = HeapAlloc(GlobalHeap, 0, 4096);
01241             if (!CalleeDataBuffer) {
01242                 MsafdReturnWithErrno( STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL );
01243                 return INVALID_SOCKET;
01244             }
01245             CalleeData.buf = CalleeDataBuffer;
01246             CalleeData.len = 4096;
01247         }
01248         else
01249         {
01250             /* Nothing */
01251             CalleeData.buf = 0;
01252             CalleeData.len = 0;
01253         }
01254 
01255         /* Call the Condition Function */
01256         CallBack = (lpfnCondition)(&CallerID,
01257                                    CallerData.buf == NULL ? NULL : &CallerData,
01258                                    NULL,
01259                                    NULL,
01260                                    &CalleeID,
01261                                    CalleeData.buf == NULL ? NULL : &CalleeData,
01262                                    &GroupID,
01263                                    dwCallbackData);
01264 
01265         if (((CallBack == CF_ACCEPT) && GroupID) != 0)
01266         {
01267             /* TBD: Check for Validity */
01268         }
01269 
01270         if (CallBack == CF_ACCEPT)
01271         {
01272             if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED) != 0)
01273             {
01274                 /* I don't support this yet */
01275             }
01276             if (CalleeData.buf)
01277             {
01278                 // SockSetConnectData Sockets(SocketID), IOCTL_AFD_SET_CONNECT_DATA, CalleeData.Buffer, CalleeData.BuffSize, 0
01279             }
01280         }
01281         else
01282         {
01283             /* Callback rejected. Build Defer Structure */
01284             DeferData.SequenceNumber = ListenReceiveData->SequenceNumber;
01285             DeferData.RejectConnection = (CallBack == CF_REJECT);
01286 
01287             /* Send IOCTL */
01288             Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
01289                                            SockEvent,
01290                                            NULL,
01291                                            NULL,
01292                                            &IOSB,
01293                                            IOCTL_AFD_DEFER_ACCEPT,
01294                                            &DeferData,
01295                                            sizeof(DeferData),
01296                                            NULL,
01297                                            0);
01298 
01299             /* Wait for return */
01300             if (Status == STATUS_PENDING)
01301             {
01302                 WaitForSingleObject(SockEvent, INFINITE);
01303                 Status = IOSB.Status;
01304             }
01305 
01306             NtClose( SockEvent );
01307 
01308             if (!NT_SUCCESS(Status))
01309             {
01310                 MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
01311                 return INVALID_SOCKET;
01312             }
01313 
01314             if (CallBack == CF_REJECT )
01315             {
01316                 *lpErrno = WSAECONNREFUSED;
01317                 return INVALID_SOCKET;
01318             }
01319             else
01320             {
01321                 *lpErrno = WSAECONNREFUSED;
01322                 return INVALID_SOCKET;
01323             }
01324         }
01325     }
01326 
01327     /* Create a new Socket */
01328     ProtocolInfo.dwCatalogEntryId = Socket->SharedData.CatalogEntryId;
01329     ProtocolInfo.dwServiceFlags1 = Socket->SharedData.ServiceFlags1;
01330     ProtocolInfo.dwProviderFlags = Socket->SharedData.ProviderFlags;
01331 
01332     AcceptSocket = WSPSocket (Socket->SharedData.AddressFamily,
01333                               Socket->SharedData.SocketType,
01334                               Socket->SharedData.Protocol,
01335                               &ProtocolInfo,
01336                               GroupID,
01337                               Socket->SharedData.CreateFlags,
01338                               lpErrno);
01339     if (AcceptSocket == INVALID_SOCKET)
01340         return INVALID_SOCKET;
01341 
01342     /* Set up the Accept Structure */
01343     AcceptData.ListenHandle = (HANDLE)AcceptSocket;
01344     AcceptData.SequenceNumber = ListenReceiveData->SequenceNumber;
01345 
01346     /* Send IOCTL to Accept */
01347     Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
01348                                    SockEvent,
01349                                    NULL,
01350                                    NULL,
01351                                    &IOSB,
01352                                    IOCTL_AFD_ACCEPT,
01353                                    &AcceptData,
01354                                    sizeof(AcceptData),
01355                                    NULL,
01356                                    0);
01357 
01358     /* Wait for return */
01359     if (Status == STATUS_PENDING)
01360     {
01361         WaitForSingleObject(SockEvent, INFINITE);
01362         Status = IOSB.Status;
01363     }
01364 
01365     if (!NT_SUCCESS(Status))
01366     {
01367         NtClose(SockEvent);
01368         WSPCloseSocket( AcceptSocket, lpErrno );
01369         MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
01370         return INVALID_SOCKET;
01371     }
01372 
01373     AcceptSocketInfo = GetSocketStructure(AcceptSocket);
01374     if (!AcceptSocketInfo)
01375     {
01376         NtClose(SockEvent);
01377         WSPCloseSocket( AcceptSocket, lpErrno );
01378         MsafdReturnWithErrno( STATUS_INVALID_CONNECTION, lpErrno, 0, NULL );
01379         return INVALID_SOCKET;
01380     }
01381 
01382     AcceptSocketInfo->SharedData.State = SocketConnected;
01383 
01384     /* Return Address in SOCKADDR FORMAT */
01385     if( SocketAddress )
01386     {
01387         RtlCopyMemory (SocketAddress,
01388                        &ListenReceiveData->Address.Address[0].AddressType,
01389                        sizeof(*RemoteAddress));
01390         if( SocketAddressLength )
01391             *SocketAddressLength = ListenReceiveData->Address.Address[0].AddressLength;
01392     }
01393 
01394     NtClose( SockEvent );
01395 
01396     /* Re-enable Async Event */
01397     SockReenableAsyncSelectEvent(Socket, FD_ACCEPT);
01398 
01399     AFD_DbgPrint(MID_TRACE,("Socket %x\n", AcceptSocket));
01400 
01401     if (Status == STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_ACCEPT))
01402     {
01403         Status = Socket->HelperData->WSHNotify(Socket->HelperContext,
01404                                                Socket->Handle,
01405                                                Socket->TdiAddressHandle,
01406                                                Socket->TdiConnectionHandle,
01407                                                WSH_NOTIFY_ACCEPT);
01408 
01409         if (Status)
01410         {
01411             if (lpErrno) *lpErrno = Status;
01412             return INVALID_SOCKET;
01413         }
01414     }
01415 
01416     *lpErrno = 0;
01417 
01418     /* Return Socket */
01419     return AcceptSocket;
01420 }
01421 
01422 int
01423 WSPAPI
01424 WSPConnect(SOCKET Handle,
01425            const struct sockaddr * SocketAddress,
01426            int SocketAddressLength,
01427            LPWSABUF lpCallerData,
01428            LPWSABUF lpCalleeData,
01429            LPQOS lpSQOS,
01430            LPQOS lpGQOS,
01431            LPINT lpErrno)
01432 {
01433     IO_STATUS_BLOCK         IOSB;
01434     PAFD_CONNECT_INFO       ConnectInfo = NULL;
01435     PSOCKET_INFORMATION     Socket;
01436     NTSTATUS                Status;
01437     INT                     Errno;
01438     ULONG                   ConnectDataLength;
01439     ULONG                   InConnectDataLength;
01440     INT                     BindAddressLength;
01441     PSOCKADDR               BindAddress;
01442     HANDLE                  SockEvent;
01443     int                     SocketDataLength;
01444 
01445     Status = NtCreateEvent(&SockEvent,
01446                            GENERIC_READ | GENERIC_WRITE,
01447                            NULL,
01448                            1,
01449                            FALSE);
01450 
01451     if (!NT_SUCCESS(Status))
01452         return MsafdReturnWithErrno(Status, lpErrno, 0, NULL);
01453 
01454     AFD_DbgPrint(MID_TRACE,("Called\n"));
01455 
01456     /* Get the Socket Structure associate to this Socket*/
01457     Socket = GetSocketStructure(Handle);
01458     if (!Socket)
01459     {
01460         NtClose(SockEvent);
01461         if (lpErrno) *lpErrno = WSAENOTSOCK;
01462         return SOCKET_ERROR;
01463     }
01464 
01465     /* Bind us First */
01466     if (Socket->SharedData.State == SocketOpen)
01467     {
01468         /* Get the Wildcard Address */
01469         BindAddressLength = Socket->HelperData->MaxWSAddressLength;
01470         BindAddress = HeapAlloc(GetProcessHeap(), 0, BindAddressLength);
01471         if (!BindAddress)
01472         {
01473             NtClose(SockEvent);
01474             return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL);
01475         }
01476         Socket->HelperData->WSHGetWildcardSockaddr (Socket->HelperContext,
01477                                                     BindAddress,
01478                                                     &BindAddressLength);
01479         /* Bind it */
01480         if (WSPBind(Handle, BindAddress, BindAddressLength, lpErrno) == SOCKET_ERROR)
01481             return SOCKET_ERROR;
01482     }
01483 
01484     /* Set the Connect Data */
01485     if (lpCallerData != NULL)
01486     {
01487         ConnectDataLength = lpCallerData->len;
01488         Status = NtDeviceIoControlFile((HANDLE)Handle,
01489                                         SockEvent,
01490                                         NULL,
01491                                         NULL,
01492                                         &IOSB,
01493                                         IOCTL_AFD_SET_CONNECT_DATA,
01494                                         lpCallerData->buf,
01495                                         ConnectDataLength,
01496                                         NULL,
01497                                         0);
01498         /* Wait for return */
01499         if (Status == STATUS_PENDING)
01500         {
01501             WaitForSingleObject(SockEvent, INFINITE);
01502             Status = IOSB.Status;
01503         }
01504 
01505         if (Status != STATUS_SUCCESS)
01506             goto notify;
01507     }
01508 
01509     /* Calculate the size of SocketAddress->sa_data */
01510     SocketDataLength = SocketAddressLength - FIELD_OFFSET(struct sockaddr, sa_data);
01511 
01512     /* Allocate a connection info buffer with SocketDataLength bytes of payload */
01513     ConnectInfo = HeapAlloc(GetProcessHeap(), 0,
01514                             FIELD_OFFSET(AFD_CONNECT_INFO,
01515                                          RemoteAddress.Address[0].Address[SocketDataLength]));
01516     if (!ConnectInfo)
01517     {
01518         Status = STATUS_INSUFFICIENT_RESOURCES;
01519         goto notify;
01520     }
01521 
01522     /* Set up Address in TDI Format */
01523     ConnectInfo->RemoteAddress.TAAddressCount = 1;
01524     ConnectInfo->RemoteAddress.Address[0].AddressLength = SocketDataLength;
01525     ConnectInfo->RemoteAddress.Address[0].AddressType = SocketAddress->sa_family;
01526     RtlCopyMemory(ConnectInfo->RemoteAddress.Address[0].Address,
01527                   SocketAddress->sa_data,
01528                   SocketDataLength);
01529 
01530     /*
01531     * Disable FD_WRITE and FD_CONNECT
01532     * The latter fixes a race condition where the FD_CONNECT is re-enabled
01533     * at the end of this function right after the Async Thread disables it.
01534     * This should only happen at the *next* WSPConnect
01535     */
01536     if (Socket->SharedData.AsyncEvents & FD_CONNECT)
01537     {
01538         Socket->SharedData.AsyncDisabledEvents |= FD_CONNECT | FD_WRITE;
01539     }
01540 
01541     /* Tell AFD that we want Connection Data back, have it allocate a buffer */
01542     if (lpCalleeData != NULL)
01543     {
01544         InConnectDataLength = lpCalleeData->len;
01545         Status = NtDeviceIoControlFile((HANDLE)Handle,
01546                                         SockEvent,
01547                                         NULL,
01548                                         NULL,
01549                                         &IOSB,
01550                                         IOCTL_AFD_SET_CONNECT_DATA_SIZE,
01551                                         &InConnectDataLength,
01552                                         sizeof(InConnectDataLength),
01553                                         NULL,
01554                                         0);
01555 
01556         /* Wait for return */
01557         if (Status == STATUS_PENDING)
01558         {
01559             WaitForSingleObject(SockEvent, INFINITE);
01560             Status = IOSB.Status;
01561         }
01562 
01563         if (Status != STATUS_SUCCESS)
01564             goto notify;
01565     }
01566 
01567     /* AFD doesn't seem to care if these are invalid, but let's 0 them anyways */
01568     ConnectInfo->Root = 0;
01569     ConnectInfo->UseSAN = FALSE;
01570     ConnectInfo->Unknown = 0;
01571 
01572     /* FIXME: Handle Async Connect */
01573     if (Socket->SharedData.NonBlocking)
01574     {
01575         AFD_DbgPrint(MIN_TRACE, ("Async Connect UNIMPLEMENTED!\n"));
01576     }
01577 
01578     /* Send IOCTL */
01579     Status = NtDeviceIoControlFile((HANDLE)Handle,
01580                                    SockEvent,
01581                                    NULL,
01582                                    NULL,
01583                                    &IOSB,
01584                                    IOCTL_AFD_CONNECT,
01585                                    ConnectInfo,
01586                                    0x22,
01587                                    NULL,
01588                                    0);
01589     /* Wait for return */
01590     if (Status == STATUS_PENDING)
01591     {
01592         WaitForSingleObject(SockEvent, INFINITE);
01593         Status = IOSB.Status;
01594     }
01595 
01596     if (Status != STATUS_SUCCESS)
01597         goto notify;
01598 
01599     Socket->SharedData.State = SocketConnected;
01600     Socket->TdiConnectionHandle = (HANDLE)IOSB.Information;
01601 
01602     /* Get any pending connect data */
01603     if (lpCalleeData != NULL)
01604     {
01605         Status = NtDeviceIoControlFile((HANDLE)Handle,
01606                                        SockEvent,
01607                                        NULL,
01608                                        NULL,
01609                                        &IOSB,
01610                                        IOCTL_AFD_GET_CONNECT_DATA,
01611                                        NULL,
01612                                        0,
01613                                        lpCalleeData->buf,
01614                                        lpCalleeData->len);
01615         /* Wait for return */
01616         if (Status == STATUS_PENDING)
01617         {
01618             WaitForSingleObject(SockEvent, INFINITE);
01619             Status = IOSB.Status;
01620         }
01621     }
01622 
01623     AFD_DbgPrint(MID_TRACE,("Ending\n"));
01624 
01625 notify:
01626     if (ConnectInfo) HeapFree(GetProcessHeap(), 0, ConnectInfo);
01627 
01628     /* Re-enable Async Event */
01629     SockReenableAsyncSelectEvent(Socket, FD_WRITE);
01630 
01631     /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */
01632     SockReenableAsyncSelectEvent(Socket, FD_CONNECT);
01633 
01634     NtClose(SockEvent);
01635 
01636     if (Status == STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_CONNECT))
01637     {
01638         Errno = Socket->HelperData->WSHNotify(Socket->HelperContext,
01639                                               Socket->Handle,
01640                                               Socket->TdiAddressHandle,
01641                                               Socket->TdiConnectionHandle,
01642                                               WSH_NOTIFY_CONNECT);
01643 
01644         if (Errno)
01645         {
01646             if (lpErrno) *lpErrno = Errno;
01647             return SOCKET_ERROR;
01648         }
01649     }
01650     else if (Status != STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_CONNECT_ERROR))
01651     {
01652         Errno = Socket->HelperData->WSHNotify(Socket->HelperContext,
01653                                               Socket->Handle,
01654                                               Socket->TdiAddressHandle,
01655                                               Socket->TdiConnectionHandle,
01656                                               WSH_NOTIFY_CONNECT_ERROR);
01657 
01658         if (Errno)
01659         {
01660             if (lpErrno) *lpErrno = Errno;
01661             return SOCKET_ERROR;
01662         }
01663     }
01664 
01665     return MsafdReturnWithErrno(Status, lpErrno, 0, NULL);
01666 }
01667 int
01668 WSPAPI
01669 WSPShutdown(SOCKET Handle,
01670             int HowTo,
01671             LPINT lpErrno)
01672 
01673 {
01674     IO_STATUS_BLOCK         IOSB;
01675     AFD_DISCONNECT_INFO     DisconnectInfo;
01676     PSOCKET_INFORMATION     Socket = NULL;
01677     NTSTATUS                Status;
01678     HANDLE                  SockEvent;
01679 
01680     Status = NtCreateEvent(&SockEvent,
01681                            GENERIC_READ | GENERIC_WRITE,
01682                            NULL,
01683                            1,
01684                            FALSE);
01685 
01686     if( !NT_SUCCESS(Status) )
01687         return -1;
01688 
01689     AFD_DbgPrint(MID_TRACE,("Called\n"));
01690 
01691     /* Get the Socket Structure associate to this Socket*/
01692     Socket = GetSocketStructure(Handle);
01693     if (!Socket)
01694     {
01695        NtClose(SockEvent);
01696        *lpErrno = WSAENOTSOCK;
01697        return SOCKET_ERROR;
01698     }
01699 
01700     /* Set AFD Disconnect Type */
01701     switch (HowTo)
01702     {
01703         case SD_RECEIVE:
01704             DisconnectInfo.DisconnectType = AFD_DISCONNECT_RECV;
01705             Socket->SharedData.ReceiveShutdown = TRUE;
01706             break;
01707         case SD_SEND:
01708             DisconnectInfo.DisconnectType= AFD_DISCONNECT_SEND;
01709             Socket->SharedData.SendShutdown = TRUE;
01710             break;
01711         case SD_BOTH:
01712             DisconnectInfo.DisconnectType = AFD_DISCONNECT_RECV | AFD_DISCONNECT_SEND;
01713             Socket->SharedData.ReceiveShutdown = TRUE;
01714             Socket->SharedData.SendShutdown = TRUE;
01715             break;
01716     }
01717 
01718     DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(-1000000);
01719 
01720     /* Send IOCTL */
01721     Status = NtDeviceIoControlFile((HANDLE)Handle,
01722                                    SockEvent,
01723                                    NULL,
01724                                    NULL,
01725                                    &IOSB,
01726                                    IOCTL_AFD_DISCONNECT,
01727                                    &DisconnectInfo,
01728                                    sizeof(DisconnectInfo),
01729                                    NULL,
01730                                    0);
01731 
01732     /* Wait for return */
01733     if (Status == STATUS_PENDING)
01734     {
01735         WaitForSingleObject(SockEvent, INFINITE);
01736         Status = IOSB.Status;
01737     }
01738 
01739     AFD_DbgPrint(MID_TRACE,("Ending\n"));
01740 
01741     NtClose( SockEvent );
01742 
01743     return MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
01744 }
01745 
01746 
01747 INT
01748 WSPAPI
01749 WSPGetSockName(IN SOCKET Handle,
01750                OUT LPSOCKADDR Name,
01751                IN OUT LPINT NameLength,
01752                OUT LPINT lpErrno)
01753 {
01754     IO_STATUS_BLOCK         IOSB;
01755     ULONG                   TdiAddressSize;
01756     PTDI_ADDRESS_INFO       TdiAddress;
01757     PTRANSPORT_ADDRESS      SocketAddress;
01758     PSOCKET_INFORMATION     Socket = NULL;
01759     NTSTATUS                Status;
01760     HANDLE                  SockEvent;
01761 
01762     Status = NtCreateEvent(&SockEvent,
01763                            GENERIC_READ | GENERIC_WRITE,
01764                            NULL,
01765                            1,
01766                            FALSE);
01767 
01768     if( !NT_SUCCESS(Status) )
01769         return SOCKET_ERROR;
01770 
01771     /* Get the Socket Structure associate to this Socket*/
01772     Socket = GetSocketStructure(Handle);
01773     if (!Socket)
01774     {
01775        NtClose(SockEvent);
01776        *lpErrno = WSAENOTSOCK;
01777        return SOCKET_ERROR;
01778     }
01779 
01780     if (!Name || !NameLength)
01781     {
01782         NtClose(SockEvent);
01783         *lpErrno = WSAEFAULT;
01784         return SOCKET_ERROR;
01785     }
01786 
01787     /* Allocate a buffer for the address */
01788     TdiAddressSize =
01789         sizeof(TRANSPORT_ADDRESS) + Socket->SharedData.SizeOfLocalAddress;
01790     TdiAddress = HeapAlloc(GlobalHeap, 0, TdiAddressSize);
01791 
01792     if ( TdiAddress == NULL )
01793     {
01794         NtClose( SockEvent );
01795         *lpErrno = WSAENOBUFS;
01796         return SOCKET_ERROR;
01797     }
01798 
01799     SocketAddress = &TdiAddress->Address;
01800 
01801     /* Send IOCTL */
01802     Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
01803                                    SockEvent,
01804                                    NULL,
01805                                    NULL,
01806                                    &IOSB,
01807                                    IOCTL_AFD_GET_SOCK_NAME,
01808                                    NULL,
01809                                    0,
01810                                    TdiAddress,
01811                                    TdiAddressSize);
01812 
01813     /* Wait for return */
01814     if (Status == STATUS_PENDING)
01815     {
01816         WaitForSingleObject(SockEvent, INFINITE);
01817         Status = IOSB.Status;
01818     }
01819 
01820     NtClose( SockEvent );
01821 
01822     if (NT_SUCCESS(Status))
01823     {
01824         if (*NameLength >= Socket->SharedData.SizeOfLocalAddress)
01825         {
01826             Name->sa_family = SocketAddress->Address[0].AddressType;
01827             RtlCopyMemory (Name->sa_data,
01828                            SocketAddress->Address[0].Address,
01829                            SocketAddress->Address[0].AddressLength);
01830             *NameLength = Socket->SharedData.SizeOfLocalAddress;
01831             AFD_DbgPrint (MID_TRACE, ("NameLength %d Address: %x Port %x\n",
01832                           *NameLength, ((struct sockaddr_in *)Name)->sin_addr.s_addr,
01833                           ((struct sockaddr_in *)Name)->sin_port));
01834             HeapFree(GlobalHeap, 0, TdiAddress);
01835             return 0;
01836         }
01837         else
01838         {
01839             HeapFree(GlobalHeap, 0, TdiAddress);
01840             *lpErrno = WSAEFAULT;
01841             return SOCKET_ERROR;
01842         }
01843     }
01844 
01845     return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL );
01846 }
01847 
01848 
01849 INT
01850 WSPAPI
01851 WSPGetPeerName(IN SOCKET s,
01852                OUT LPSOCKADDR Name,
01853                IN OUT LPINT NameLength,
01854                OUT LPINT lpErrno)
01855 {
01856     IO_STATUS_BLOCK         IOSB;
01857     ULONG                   TdiAddressSize;
01858     PTRANSPORT_ADDRESS      SocketAddress;
01859     PSOCKET_INFORMATION     Socket = NULL;
01860     NTSTATUS                Status;
01861     HANDLE                  SockEvent;
01862 
01863     Status = NtCreateEvent(&SockEvent,
01864                            GENERIC_READ | GENERIC_WRITE,
01865                            NULL,
01866                            1,
01867                            FALSE);
01868 
01869     if( !NT_SUCCESS(Status) )
01870         return SOCKET_ERROR;
01871 
01872     /* Get the Socket Structure associate to this Socket*/
01873     Socket = GetSocketStructure(s);
01874     if (!Socket)
01875     {
01876        NtClose(SockEvent);
01877        *lpErrno = WSAENOTSOCK;
01878        return SOCKET_ERROR;
01879     }
01880 
01881     if (Socket->SharedData.State != SocketConnected)
01882     {
01883         NtClose(SockEvent);
01884         *lpErrno = WSAENOTCONN;
01885         return SOCKET_ERROR;
01886     }
01887 
01888     if (!Name || !NameLength)
01889     {
01890         NtClose(SockEvent);
01891         *lpErrno = WSAEFAULT;
01892         return SOCKET_ERROR;
01893     }
01894 
01895     /* Allocate a buffer for the address */
01896     TdiAddressSize = sizeof(TRANSPORT_ADDRESS) + Socket->SharedData.SizeOfRemoteAddress;
01897     SocketAddress = HeapAlloc(GlobalHeap, 0, TdiAddressSize);
01898 
01899     if ( SocketAddress == NULL )
01900     {
01901         NtClose( SockEvent );
01902         *lpErrno = WSAENOBUFS;
01903         return SOCKET_ERROR;
01904     }
01905 
01906     /* Send IOCTL */
01907     Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
01908                                    SockEvent,
01909                                    NULL,
01910                                    NULL,
01911                                    &IOSB,
01912                                    IOCTL_AFD_GET_PEER_NAME,
01913                                    NULL,
01914                                    0,
01915                                    SocketAddress,
01916                                    TdiAddressSize);
01917 
01918     /* Wait for return */
01919     if (Status == STATUS_PENDING)
01920     {
01921         WaitForSingleObject(SockEvent, INFINITE);
01922         Status = IOSB.Status;
01923     }
01924 
01925     NtClose( SockEvent );
01926 
01927     if (NT_SUCCESS(Status))
01928     {
01929         if (*NameLength >= Socket->SharedData.SizeOfRemoteAddress)
01930         {
01931             Name->sa_family = SocketAddress->Address[0].AddressType;
01932             RtlCopyMemory (Name->sa_data,
01933                            SocketAddress->Address[0].Address,
01934                            SocketAddress->Address[0].AddressLength);
01935             *NameLength = Socket->SharedData.SizeOfRemoteAddress;
01936             AFD_DbgPrint (MID_TRACE, ("NameLength %d Address: %s Port %x\n",
01937                           *NameLength, ((struct sockaddr_in *)Name)->sin_addr.s_addr,
01938                           ((struct sockaddr_in *)Name)->sin_port));
01939             HeapFree(GlobalHeap, 0, SocketAddress);
01940             return 0;
01941         }
01942         else
01943         {
01944             HeapFree(GlobalHeap, 0, SocketAddress);
01945             *lpErrno = WSAEFAULT;
01946             return SOCKET_ERROR;
01947         }
01948     }
01949 
01950     return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL );
01951 }
01952 
01953 INT
01954 WSPAPI
01955 WSPIoctl(IN  SOCKET Handle,
01956          IN  DWORD dwIoControlCode,
01957          IN  LPVOID lpvInBuffer,
01958          IN  DWORD cbInBuffer,
01959          OUT LPVOID lpvOutBuffer,
01960          IN  DWORD cbOutBuffer,
01961          OUT LPDWORD lpcbBytesReturned,
01962          IN  LPWSAOVERLAPPED lpOverlapped,
01963          IN  LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
01964          IN  LPWSATHREADID lpThreadId,
01965          OUT LPINT lpErrno)
01966 {
01967     PSOCKET_INFORMATION Socket = NULL;
01968     BOOLEAN NeedsCompletion;
01969     BOOLEAN NonBlocking;
01970 
01971     /* Get the Socket Structure associate to this Socket*/
01972     Socket = GetSocketStructure(Handle);
01973     if (!Socket)
01974     {
01975        *lpErrno = WSAENOTSOCK;
01976        return SOCKET_ERROR;
01977     }
01978 
01979     *lpcbBytesReturned = 0;
01980 
01981     switch( dwIoControlCode )
01982     {
01983         case FIONBIO:
01984             if( cbInBuffer < sizeof(INT) || IS_INTRESOURCE(lpvInBuffer) )
01985             {
01986                 *lpErrno = WSAEFAULT;
01987                 return SOCKET_ERROR;
01988             }
01989             NonBlocking = *((PULONG)lpvInBuffer) ? TRUE : FALSE;
01990             Socket->SharedData.NonBlocking = NonBlocking ? 1 : 0;
01991             *lpErrno = SetSocketInformation(Socket, AFD_INFO_BLOCKING_MODE, &NonBlocking, NULL, NULL);
01992             if (*lpErrno != NO_ERROR)
01993                 return SOCKET_ERROR;
01994             else
01995                 return NO_ERROR;
01996         case FIONREAD:
01997             if( cbOutBuffer < sizeof(INT) || IS_INTRESOURCE(lpvOutBuffer) )
01998             {
01999                 *lpErrno = WSAEFAULT;
02000                 return SOCKET_ERROR;
02001             }
02002             *lpErrno = GetSocketInformation(Socket, AFD_INFO_RECEIVE_CONTENT_SIZE, NULL, (PULONG)lpvOutBuffer, NULL);
02003             if (*lpErrno != NO_ERROR)
02004                 return SOCKET_ERROR;
02005             else
02006             {
02007                 *lpcbBytesReturned = sizeof(ULONG);
02008                 return NO_ERROR;
02009             }
02010         case SIO_GET_EXTENSION_FUNCTION_POINTER:
02011             *lpErrno = WSAEINVAL;
02012             return SOCKET_ERROR;
02013         default:
02014             *lpErrno = Socket->HelperData->WSHIoctl(Socket->HelperContext,
02015                                                     Handle,
02016                                                     Socket->TdiAddressHandle,
02017                                                     Socket->TdiConnectionHandle,
02018                                                     dwIoControlCode,
02019                                                     lpvInBuffer,
02020                                                     cbInBuffer,
02021                                                     lpvOutBuffer,
02022                                                     cbOutBuffer,
02023                                                     lpcbBytesReturned,
02024                                                     lpOverlapped,
02025                                                     lpCompletionRoutine,
02026                                                     (LPBOOL)&NeedsCompletion);
02027 
02028             if (*lpErrno != NO_ERROR)
02029                 return SOCKET_ERROR;
02030             else
02031                 return NO_ERROR;
02032     }
02033 }
02034 
02035 
02036 INT
02037 WSPAPI
02038 WSPGetSockOpt(IN SOCKET Handle,
02039               IN INT Level,
02040               IN INT OptionName,
02041               OUT CHAR FAR* OptionValue,
02042               IN OUT LPINT OptionLength,
02043               OUT LPINT lpErrno)
02044 {
02045     PSOCKET_INFORMATION Socket = NULL;
02046     PVOID Buffer;
02047     INT BufferSize;
02048     BOOL BoolBuffer;
02049 
02050     /* Get the Socket Structure associate to this Socket*/
02051     Socket = GetSocketStructure(Handle);
02052     if (Socket == NULL)
02053     {
02054         *lpErrno = WSAENOTSOCK;
02055         return SOCKET_ERROR;
02056     }
02057 
02058     AFD_DbgPrint(MID_TRACE, ("Called\n"));
02059 
02060     switch (Level)
02061     {
02062         case SOL_SOCKET:
02063             switch (OptionName)
02064             {
02065                 case SO_TYPE:
02066                     Buffer = &Socket->SharedData.SocketType;
02067                     BufferSize = sizeof(INT);
02068                     break;
02069 
02070                 case SO_RCVBUF:
02071                     Buffer = &Socket->SharedData.SizeOfRecvBuffer;
02072                     BufferSize = sizeof(INT);
02073                     break;
02074 
02075                 case SO_SNDBUF:
02076                     Buffer = &Socket->SharedData.SizeOfSendBuffer;
02077                     BufferSize = sizeof(INT);
02078                     break;
02079 
02080                 case SO_ACCEPTCONN:
02081                     BoolBuffer = Socket->SharedData.Listening;
02082                     Buffer = &BoolBuffer;
02083                     BufferSize = sizeof(BOOL);
02084                     break;
02085 
02086                 case SO_BROADCAST:
02087                     BoolBuffer = Socket->SharedData.Broadcast;
02088                     Buffer = &BoolBuffer;
02089                     BufferSize = sizeof(BOOL);
02090                     break;
02091 
02092                 case SO_DEBUG:
02093                     BoolBuffer = Socket->SharedData.Debug;
02094                     Buffer = &BoolBuffer;
02095                     BufferSize = sizeof(BOOL);
02096                     break;
02097 
02098                 case SO_DONTLINGER:
02099                     BoolBuffer = (Socket->SharedData.LingerData.l_onoff == 0);
02100                     Buffer = &BoolBuffer;
02101                     BufferSize = sizeof(BOOL);
02102                     break;
02103 
02104                 case SO_LINGER:
02105                     Buffer = &Socket->SharedData.LingerData;
02106                     BufferSize = sizeof(struct linger);
02107                     break;
02108 
02109                 /* case SO_CONDITIONAL_ACCEPT: */
02110                 case SO_DONTROUTE:
02111                 case SO_ERROR:
02112                 case SO_GROUP_ID:
02113                 case SO_GROUP_PRIORITY:
02114                 case SO_KEEPALIVE:
02115                 case SO_MAX_MSG_SIZE:
02116                 case SO_OOBINLINE:
02117                 case SO_PROTOCOL_INFO:
02118                 case SO_REUSEADDR:
02119                     AFD_DbgPrint(MID_TRACE, ("Unimplemented option (%x)\n",
02120                                  OptionName));
02121 
02122                 default:
02123                     *lpErrno = WSAEINVAL;
02124                     return SOCKET_ERROR;
02125             }
02126 
02127             if (*OptionLength < BufferSize)
02128             {
02129                 *lpErrno = WSAEFAULT;
02130                 *OptionLength = BufferSize;
02131                 return SOCKET_ERROR;
02132             }
02133             RtlCopyMemory(OptionValue, Buffer, BufferSize);
02134 
02135             return 0;
02136 
02137         case IPPROTO_TCP: /* FIXME */
02138         default:
02139             *lpErrno = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext,
02140                                                                    Handle,
02141                                                                    Socket->TdiAddressHandle,
02142                                                                    Socket->TdiConnectionHandle,
02143                                                                    Level,
02144                                                                    OptionName,
02145                                                                    OptionValue,
02146                                                                    (LPINT)OptionLength);
02147             return (*lpErrno == 0) ? 0 : SOCKET_ERROR;
02148     }
02149 }
02150 
02151 INT
02152 WSPAPI
02153 WSPSetSockOpt(
02154     IN  SOCKET s,
02155     IN  INT level,
02156     IN  INT optname,
02157     IN  CONST CHAR FAR* optval,
02158     IN  INT optlen,
02159     OUT LPINT lpErrno)
02160 {
02161     PSOCKET_INFORMATION Socket;
02162 
02163     /* Get the Socket Structure associate to this Socket*/
02164     Socket = GetSocketStructure(s);
02165     if (Socket == NULL)
02166     {
02167         *lpErrno = WSAENOTSOCK;
02168         return SOCKET_ERROR;
02169     }
02170 
02171 
02172     /* FIXME: We should handle some more cases here */
02173     if (level == SOL_SOCKET)
02174     {
02175         switch (optname)
02176         {
02177            case SO_BROADCAST:
02178               if (optlen < sizeof(BOOL))
02179               {
02180                   *lpErrno = WSAEFAULT;
02181                   return SOCKET_ERROR;
02182               }
02183               Socket->SharedData.Broadcast = (*optval != 0) ? 1 : 0;
02184               return 0;
02185 
02186            case SO_DONTLINGER:
02187               if (optlen < sizeof(BOOL))
02188               {
02189                   *lpErrno = WSAEFAULT;
02190                   return SOCKET_ERROR;
02191               }
02192               Socket->SharedData.LingerData.l_onoff = (*optval != 0) ? 0 : 1;
02193               return 0;
02194 
02195            case SO_LINGER:
02196               if (optlen < sizeof(struct linger))
02197               {
02198                   *lpErrno = WSAEFAULT;
02199                   return SOCKET_ERROR;
02200               }
02201               RtlCopyMemory(&Socket->SharedData.LingerData,
02202                             optval,
02203                             sizeof(struct linger));
02204               return 0;
02205 
02206            case SO_SNDBUF:
02207               if (optlen < sizeof(DWORD))
02208               {
02209                   *lpErrno = WSAEFAULT;
02210                   return SOCKET_ERROR;
02211               }
02212 
02213               /* TODO: The total per-socket buffer space reserved for sends */
02214               AFD_DbgPrint(MIN_TRACE,("Setting send buf to %x is not implemented yet\n", optval));
02215               return 0;
02216 
02217            default:
02218               AFD_DbgPrint(MIN_TRACE,("Unknown optname %x\n", optname));
02219               break;
02220         }
02221     }
02222 
02223 
02224     *lpErrno = Socket->HelperData->WSHSetSocketInformation(Socket->HelperContext,
02225                                                            s,
02226                                                            Socket->TdiAddressHandle,
02227                                                            Socket->TdiConnectionHandle,
02228                                                            level,
02229                                                            optname,
02230                                                            (PCHAR)optval,
02231                                                            optlen);
02232     return (*lpErrno == 0) ? 0 : SOCKET_ERROR;
02233 }
02234 
02235 /*
02236  * FUNCTION: Initialize service provider for a client
02237  * ARGUMENTS:
02238  *     wVersionRequested = Highest WinSock SPI version that the caller can use
02239  *     lpWSPData         = Address of WSPDATA structure to initialize
02240  *     lpProtocolInfo    = Pointer to structure that defines the desired protocol
02241  *     UpcallTable       = Pointer to upcall table of the WinSock DLL
02242  *     lpProcTable       = Address of procedure table to initialize
02243  * RETURNS:
02244  *     Status of operation
02245  */
02246 INT
02247 WSPAPI
02248 WSPStartup(IN  WORD wVersionRequested,
02249            OUT LPWSPDATA lpWSPData,
02250            IN  LPWSAPROTOCOL_INFOW lpProtocolInfo,
02251            IN  WSPUPCALLTABLE UpcallTable,
02252            OUT LPWSPPROC_TABLE lpProcTable)
02253 
02254 {
02255     NTSTATUS Status;
02256 
02257     AFD_DbgPrint(MAX_TRACE, ("wVersionRequested (0x%X) \n", wVersionRequested));
02258     Status = NO_ERROR;
02259     Upcalls = UpcallTable;
02260 
02261     if (Status == NO_ERROR)
02262     {
02263         lpProcTable->lpWSPAccept = WSPAccept;
02264         lpProcTable->lpWSPAddressToString = WSPAddressToString;
02265         lpProcTable->lpWSPAsyncSelect = WSPAsyncSelect;
02266         lpProcTable->lpWSPBind = WSPBind;
02267         lpProcTable->lpWSPCancelBlockingCall = WSPCancelBlockingCall;
02268         lpProcTable->lpWSPCleanup = WSPCleanup;
02269         lpProcTable->lpWSPCloseSocket = WSPCloseSocket;
02270         lpProcTable->lpWSPConnect = WSPConnect;
02271         lpProcTable->lpWSPDuplicateSocket = WSPDuplicateSocket;
02272         lpProcTable->lpWSPEnumNetworkEvents = WSPEnumNetworkEvents;
02273         lpProcTable->lpWSPEventSelect = WSPEventSelect;
02274         lpProcTable->lpWSPGetOverlappedResult = WSPGetOverlappedResult;
02275         lpProcTable->lpWSPGetPeerName = WSPGetPeerName;
02276         lpProcTable->lpWSPGetSockName = WSPGetSockName;
02277         lpProcTable->lpWSPGetSockOpt = WSPGetSockOpt;
02278         lpProcTable->lpWSPGetQOSByName = WSPGetQOSByName;
02279         lpProcTable->lpWSPIoctl = WSPIoctl;
02280         lpProcTable->lpWSPJoinLeaf = WSPJoinLeaf;
02281         lpProcTable->lpWSPListen = WSPListen;
02282         lpProcTable->lpWSPRecv = WSPRecv;
02283         lpProcTable->lpWSPRecvDisconnect = WSPRecvDisconnect;
02284         lpProcTable->lpWSPRecvFrom = WSPRecvFrom;
02285         lpProcTable->lpWSPSelect = WSPSelect;
02286         lpProcTable->lpWSPSend = WSPSend;
02287         lpProcTable->lpWSPSendDisconnect = WSPSendDisconnect;
02288         lpProcTable->lpWSPSendTo = WSPSendTo;
02289         lpProcTable->lpWSPSetSockOpt = WSPSetSockOpt;
02290         lpProcTable->lpWSPShutdown = WSPShutdown;
02291         lpProcTable->lpWSPSocket = WSPSocket;
02292         lpProcTable->lpWSPStringToAddress = WSPStringToAddress;
02293         lpWSPData->wVersion     = MAKEWORD(2, 2);
02294         lpWSPData->wHighVersion = MAKEWORD(2, 2);
02295     }
02296 
02297     AFD_DbgPrint(MAX_TRACE, ("Status (%d).\n", Status));
02298 
02299     return Status;
02300 }
02301 
02302 
02303 /*
02304  * FUNCTION: Cleans up service provider for a client
02305  * ARGUMENTS:
02306  *     lpErrno = Address of buffer for error information
02307  * RETURNS:
02308  *     0 if successful, or SOCKET_ERROR if not
02309  */
02310 INT
02311 WSPAPI
02312 WSPCleanup(OUT LPINT lpErrno)
02313 
02314 {
02315     AFD_DbgPrint(MAX_TRACE, ("\n"));
02316     AFD_DbgPrint(MAX_TRACE, ("Leaving.\n"));
02317     *lpErrno = NO_ERROR;
02318 
02319     return 0;
02320 }
02321 
02322 
02323 
02324 int
02325 GetSocketInformation(PSOCKET_INFORMATION Socket,
02326                      ULONG AfdInformationClass,
02327                      PBOOLEAN Boolean OPTIONAL,
02328                      PULONG Ulong OPTIONAL,
02329                      PLARGE_INTEGER LargeInteger OPTIONAL)
02330 {
02331     IO_STATUS_BLOCK     IOSB;
02332     AFD_INFO            InfoData;
02333     NTSTATUS            Status;
02334     HANDLE              SockEvent;
02335 
02336     Status = NtCreateEvent(&SockEvent,
02337                            GENERIC_READ | GENERIC_WRITE,
02338                            NULL,
02339                            1,
02340                            FALSE);
02341 
02342     if( !NT_SUCCESS(Status) )
02343         return -1;
02344 
02345     /* Set Info Class */
02346     InfoData.InformationClass = AfdInformationClass;
02347 
02348     /* Send IOCTL */
02349     Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
02350                                    SockEvent,
02351                                    NULL,
02352                                    NULL,
02353                                    &IOSB,
02354                                    IOCTL_AFD_GET_INFO,
02355                                    &InfoData,
02356                                    sizeof(InfoData),
02357                                    &InfoData,
02358                                    sizeof(InfoData));
02359 
02360     /* Wait for return */
02361     if (Status == STATUS_PENDING)
02362     {
02363         WaitForSingleObject(SockEvent, INFINITE);
02364         Status = IOSB.Status;
02365     }
02366 
02367     if (Status != STATUS_SUCCESS)
02368         return -1;
02369 
02370     /* Return Information */
02371     if (Ulong != NULL)
02372     {
02373         *Ulong = InfoData.Information.Ulong;
02374     }
02375     if (LargeInteger != NULL)
02376     {
02377         *LargeInteger = InfoData.Information.LargeInteger;
02378     }
02379     if (Boolean != NULL)
02380     {
02381         *Boolean = InfoData.Information.Boolean;
02382     }
02383 
02384     NtClose( SockEvent );
02385 
02386     return 0;
02387 
02388 }
02389 
02390 
02391 int
02392 SetSocketInformation(PSOCKET_INFORMATION Socket,
02393                      ULONG AfdInformationClass,
02394                      PBOOLEAN Boolean OPTIONAL,
02395                      PULONG Ulong OPTIONAL,
02396                      PLARGE_INTEGER LargeInteger OPTIONAL)
02397 {
02398     IO_STATUS_BLOCK     IOSB;
02399     AFD_INFO            InfoData;
02400     NTSTATUS            Status;
02401     HANDLE              SockEvent;
02402 
02403     Status = NtCreateEvent(&SockEvent,
02404                            GENERIC_READ | GENERIC_WRITE,
02405                            NULL,
02406                            1,
02407                            FALSE);
02408 
02409     if( !NT_SUCCESS(Status) )
02410         return -1;
02411 
02412     /* Set Info Class */
02413     InfoData.InformationClass = AfdInformationClass;
02414 
02415     /* Set Information */
02416     if (Ulong != NULL)
02417     {
02418         InfoData.Information.Ulong = *Ulong;
02419     }
02420     if (LargeInteger != NULL)
02421     {
02422         InfoData.Information.LargeInteger = *LargeInteger;
02423     }
02424     if (Boolean != NULL)
02425     {
02426         InfoData.Information.Boolean = *Boolean;
02427     }
02428 
02429     /* Send IOCTL */
02430     Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
02431                                    SockEvent,
02432                                    NULL,
02433                                    NULL,
02434                                    &IOSB,
02435                                    IOCTL_AFD_SET_INFO,
02436                                    &InfoData,
02437                                    sizeof(InfoData),
02438                                    NULL,
02439                                    0);
02440 
02441     /* Wait for return */
02442     if (Status == STATUS_PENDING)
02443     {
02444         WaitForSingleObject(SockEvent, INFINITE);
02445         Status = IOSB.Status;
02446     }
02447 
02448     NtClose( SockEvent );
02449 
02450     return Status == STATUS_SUCCESS ? 0 : -1;
02451 
02452 }
02453 
02454 PSOCKET_INFORMATION
02455 GetSocketStructure(SOCKET Handle)
02456 {
02457     PSOCKET_INFORMATION CurrentSocket;
02458 
02459     EnterCriticalSection(&SocketListLock);
02460 
02461     CurrentSocket = SocketListHead;
02462     while (CurrentSocket)
02463     {
02464         if (CurrentSocket->Handle == Handle)
02465         {
02466             LeaveCriticalSection(&SocketListLock);
02467             return CurrentSocket;
02468         }
02469 
02470         CurrentSocket = CurrentSocket->NextSocket;
02471     }
02472 
02473     LeaveCriticalSection(&SocketListLock);
02474 
02475     return NULL;
02476 }
02477 
02478 int CreateContext(PSOCKET_INFORMATION Socket)
02479 {
02480     IO_STATUS_BLOCK     IOSB;
02481     SOCKET_CONTEXT      ContextData;
02482     NTSTATUS            Status;
02483     HANDLE              SockEvent;
02484 
02485     Status = NtCreateEvent(&SockEvent,
02486                            GENERIC_READ | GENERIC_WRITE,
02487                            NULL,
02488                            1,
02489                            FALSE);
02490 
02491     if( !NT_SUCCESS(Status) )
02492         return -1;
02493 
02494     /* Create Context */
02495     ContextData.SharedData = Socket->SharedData;
02496     ContextData.SizeOfHelperData = 0;
02497     RtlCopyMemory (&ContextData.LocalAddress,
02498                    Socket->LocalAddress,
02499                    Socket->SharedData.SizeOfLocalAddress);
02500     RtlCopyMemory (&ContextData.RemoteAddress,
02501                    Socket->RemoteAddress,
02502                    Socket->SharedData.SizeOfRemoteAddress);
02503 
02504     /* Send IOCTL */
02505     Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
02506                                    SockEvent,
02507                                    NULL,
02508                                    NULL,
02509                                    &IOSB,
02510                                    IOCTL_AFD_SET_CONTEXT,
02511                                    &ContextData,
02512                                    sizeof(ContextData),
02513                                    NULL,
02514                                    0);
02515 
02516     /* Wait for Completition */
02517     if (Status == STATUS_PENDING)
02518     {
02519         WaitForSingleObject(SockEvent, INFINITE);
02520         Status = IOSB.Status;
02521     }
02522 
02523     NtClose( SockEvent );
02524 
02525     return Status == STATUS_SUCCESS ? 0 : -1;
02526 }
02527 
02528 BOOLEAN SockCreateOrReferenceAsyncThread(VOID)
02529 {
02530     HANDLE hAsyncThread;
02531     DWORD AsyncThreadId;
02532     HANDLE AsyncEvent;
02533     OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags;
02534     NTSTATUS Status;
02535 
02536     /* Check if the Thread Already Exists */
02537     if (SockAsyncThreadRefCount)
02538     {
02539         ASSERT(SockAsyncCompletionPort);
02540         return TRUE;
02541     }
02542 
02543     /* Create the Completion Port */
02544     if (!SockAsyncCompletionPort)
02545     {
02546         Status = NtCreateIoCompletion(&SockAsyncCompletionPort,
02547                                       IO_COMPLETION_ALL_ACCESS,
02548                                       NULL,
02549                                       2); // Allow 2 threads only
02550         if (!NT_SUCCESS(Status))
02551         {
02552              AFD_DbgPrint(MID_TRACE,("Failed to create completion port\n"));
02553              return FALSE;
02554         }
02555         /* Protect Handle */
02556         HandleFlags.ProtectFromClose = TRUE;
02557         HandleFlags.Inherit = FALSE;
02558         Status = NtSetInformationObject(SockAsyncCompletionPort,
02559                                         ObjectHandleFlagInformation,
02560                                         &HandleFlags,
02561                                         sizeof(HandleFlags));
02562     }
02563 
02564     /* Create the Async Event */
02565     Status = NtCreateEvent(&AsyncEvent,
02566                            EVENT_ALL_ACCESS,
02567                            NULL,
02568                            NotificationEvent,
02569                            FALSE);
02570 
02571     /* Create the Async Thread */
02572     hAsyncThread = CreateThread(NULL,
02573                                 0,
02574                                 (LPTHREAD_START_ROUTINE)SockAsyncThread,
02575                                 NULL,
02576                                 0,
02577                                 &AsyncThreadId);
02578 
02579     /* Close the Handle */
02580     NtClose(hAsyncThread);
02581 
02582     /* Increase the Reference Count */
02583     SockAsyncThreadRefCount++;
02584     return TRUE;
02585 }
02586 
02587 int SockAsyncThread(PVOID ThreadParam)
02588 {
02589     PVOID AsyncContext;
02590     PASYNC_COMPLETION_ROUTINE AsyncCompletionRoutine;
02591     IO_STATUS_BLOCK IOSB;
02592     NTSTATUS Status;
02593 
02594     /* Make the Thread Higher Priority */
02595     SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
02596 
02597     /* Do a KQUEUE/WorkItem Style Loop, thanks to IoCompletion Ports */
02598     do
02599     {
02600         Status =  NtRemoveIoCompletion (SockAsyncCompletionPort,
02601                                         (PVOID*)&AsyncCompletionRoutine,
02602                                         &AsyncContext,
02603                                         &IOSB,
02604                                         NULL);
02605         /* Call the Async Function */
02606         if (NT_SUCCESS(Status))
02607         {
02608             (*AsyncCompletionRoutine)(AsyncContext, &IOSB);
02609         }
02610         else
02611         {
02612             /* It Failed, sleep for a second */
02613             Sleep(1000);
02614         }
02615     } while ((Status != STATUS_TIMEOUT));
02616 
02617     /* The Thread has Ended */
02618     return 0;
02619 }
02620 
02621 BOOLEAN SockGetAsyncSelectHelperAfdHandle(VOID)
02622 {
02623     UNICODE_STRING AfdHelper;
02624     OBJECT_ATTRIBUTES ObjectAttributes;
02625     IO_STATUS_BLOCK IoSb;
02626     FILE_COMPLETION_INFORMATION CompletionInfo;
02627     OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags;
02628 
02629     /* First, make sure we're not already intialized */
02630     if (SockAsyncHelperAfdHandle)
02631     {
02632         return TRUE;
02633     }
02634 
02635     /* Set up Handle Name and Object */
02636     RtlInitUnicodeString(&AfdHelper, L"\\Device\\Afd\\AsyncSelectHlp" );
02637                          InitializeObjectAttributes(&ObjectAttributes,
02638                          &AfdHelper,
02639                          OBJ_INHERIT | OBJ_CASE_INSENSITIVE,
02640                          NULL,
02641                          NULL);
02642 
02643     /* Open the Handle to AFD */
02644     NtCreateFile(&SockAsyncHelperAfdHandle,
02645                  GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
02646                  &ObjectAttributes,
02647                  &IoSb,
02648                  NULL,
02649                  0,
02650                  FILE_SHARE_READ | FILE_SHARE_WRITE,
02651                  FILE_OPEN_IF,
02652                  0,
02653                  NULL,
02654                  0);
02655 
02656     /*
02657      * Now Set up the Completion Port Information
02658      * This means that whenever a Poll is finished, the routine will be executed
02659      */
02660     CompletionInfo.Port = SockAsyncCompletionPort;
02661     CompletionInfo.Key = SockAsyncSelectCompletionRoutine;
02662     NtSetInformationFile(SockAsyncHelperAfdHandle,
02663                          &IoSb,
02664                          &CompletionInfo,
02665                          sizeof(CompletionInfo),
02666                          FileCompletionInformation);
02667 
02668 
02669     /* Protect the Handle */
02670     HandleFlags.ProtectFromClose = TRUE;
02671     HandleFlags.Inherit = FALSE;
02672     NtSetInformationObject(SockAsyncCompletionPort,
02673                            ObjectHandleFlagInformation,
02674                            &HandleFlags,
02675                            sizeof(HandleFlags));
02676 
02677 
02678     /* Set this variable to true so that Send/Recv/Accept will know wether to renable disabled events */
02679     SockAsyncSelectCalled = TRUE;
02680     return TRUE;
02681 }
02682 
02683 VOID SockAsyncSelectCompletionRoutine(PVOID Context, PIO_STATUS_BLOCK IoStatusBlock)
02684 {
02685 
02686     PASYNC_DATA AsyncData = Context;
02687     PSOCKET_INFORMATION Socket;
02688     ULONG x;
02689 
02690     /* Get the Socket */
02691     Socket = AsyncData->ParentSocket;
02692 
02693     /* Check if the Sequence  Number Changed behind our back */
02694     if (AsyncData->SequenceNumber != Socket->SharedData.SequenceNumber )
02695     {
02696         return;
02697     }
02698 
02699     /* Check we were manually called b/c of a failure */
02700     if (!NT_SUCCESS(IoStatusBlock->Status))
02701     {
02702         /* FIXME: Perform Upcall */
02703         return;
02704     }
02705 
02706     for (x = 1; x; x<<=1)
02707     {
02708         switch (AsyncData->AsyncSelectInfo.Handles[0].Events & x)
02709         {
02710             case AFD_EVENT_RECEIVE:
02711                 if (0 != (Socket->SharedData.AsyncEvents & FD_READ) &&
02712                     0 == (Socket->SharedData.AsyncDisabledEvents & FD_READ))
02713                 {
02714                     /* Make the Notifcation */
02715                     (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
02716                                                Socket->SharedData.wMsg,
02717                                                Socket->Handle,
02718                                                WSAMAKESELECTREPLY(FD_READ, 0));
02719                     /* Disable this event until the next read(); */
02720                     Socket->SharedData.AsyncDisabledEvents |= FD_READ;
02721                 }
02722             break;
02723 
02724             case AFD_EVENT_OOB_RECEIVE:
02725             if (0 != (Socket->SharedData.AsyncEvents & FD_OOB) &&
02726                 0 == (Socket->SharedData.AsyncDisabledEvents & FD_OOB))
02727             {
02728                 /* Make the Notifcation */
02729                 (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
02730                                            Socket->SharedData.wMsg,
02731                                            Socket->Handle,
02732                                            WSAMAKESELECTREPLY(FD_OOB, 0));
02733                 /* Disable this event until the next read(); */
02734                 Socket->SharedData.AsyncDisabledEvents |= FD_OOB;
02735             }
02736             break;
02737 
02738             case AFD_EVENT_SEND:
02739                 if (0 != (Socket->SharedData.AsyncEvents & FD_WRITE) &&
02740                     0 == (Socket->SharedData.AsyncDisabledEvents & FD_WRITE))
02741                 {
02742                     /* Make the Notifcation */
02743                     (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
02744                                                Socket->SharedData.wMsg,
02745                                                Socket->Handle,
02746                                                WSAMAKESELECTREPLY(FD_WRITE, 0));
02747                     /* Disable this event until the next write(); */
02748                     Socket->SharedData.AsyncDisabledEvents |= FD_WRITE;
02749                 }
02750                 break;
02751 
02752                 /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */
02753             case AFD_EVENT_CONNECT:
02754             case AFD_EVENT_CONNECT_FAIL:
02755                 if (0 != (Socket->SharedData.AsyncEvents & FD_CONNECT) &&
02756                     0 == (Socket->SharedData.AsyncDisabledEvents & FD_CONNECT))
02757                 {
02758                     /* Make the Notifcation */
02759                     (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
02760                         Socket->SharedData.wMsg,
02761                         Socket->Handle,
02762                         WSAMAKESELECTREPLY(FD_CONNECT, 0));
02763                     /* Disable this event forever; */
02764                     Socket->SharedData.AsyncDisabledEvents |= FD_CONNECT;
02765                 }
02766                 break;
02767 
02768             case AFD_EVENT_ACCEPT:
02769                 if (0 != (Socket->SharedData.AsyncEvents & FD_ACCEPT) &&
02770                     0 == (Socket->SharedData.AsyncDisabledEvents & FD_ACCEPT))
02771                 {
02772                     /* Make the Notifcation */
02773                     (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
02774                                                Socket->SharedData.wMsg,
02775                                                Socket->Handle,
02776                                                WSAMAKESELECTREPLY(FD_ACCEPT, 0));
02777                     /* Disable this event until the next accept(); */
02778                     Socket->SharedData.AsyncDisabledEvents |= FD_ACCEPT;
02779                 }
02780                 break;
02781 
02782             case AFD_EVENT_DISCONNECT:
02783             case AFD_EVENT_ABORT:
02784             case AFD_EVENT_CLOSE:
02785                 if (0 != (Socket->SharedData.AsyncEvents & FD_CLOSE) &&
02786                     0 == (Socket->SharedData.AsyncDisabledEvents & FD_CLOSE))
02787                 {
02788                     /* Make the Notifcation */
02789                     (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
02790                                                Socket->SharedData.wMsg,
02791                                                Socket->Handle,
02792                                                WSAMAKESELECTREPLY(FD_CLOSE, 0));
02793                     /* Disable this event forever; */
02794                     Socket->SharedData.AsyncDisabledEvents |= FD_CLOSE;
02795                 }
02796                  break;
02797             /* FIXME: Support QOS */
02798         }
02799     }
02800 
02801     /* Check if there are any events left for us to check */
02802     if ((Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents)) == 0 )
02803     {
02804         return;
02805     }
02806 
02807     /* Keep Polling */
02808     SockProcessAsyncSelect(Socket, AsyncData);
02809     return;
02810 }
02811 
02812 VOID SockProcessAsyncSelect(PSOCKET_INFORMATION Socket, PASYNC_DATA AsyncData)
02813 {
02814 
02815     ULONG lNetworkEvents;
02816     NTSTATUS Status;
02817 
02818     /* Set up the Async Data Event Info */
02819     AsyncData->AsyncSelectInfo.Timeout.HighPart = 0x7FFFFFFF;
02820     AsyncData->AsyncSelectInfo.Timeout.LowPart = 0xFFFFFFFF;
02821     AsyncData->AsyncSelectInfo.HandleCount = 1;
02822     AsyncData->AsyncSelectInfo.Exclusive = TRUE;
02823     AsyncData->AsyncSelectInfo.Handles[0].Handle = Socket->Handle;
02824     AsyncData->AsyncSelectInfo.Handles[0].Events = 0;
02825 
02826     /* Remove unwanted events */
02827     lNetworkEvents = Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents);
02828 
02829     /* Set Events to wait for */
02830     if (lNetworkEvents & FD_READ)
02831     {
02832         AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_RECEIVE;
02833     }
02834 
02835     if (lNetworkEvents & FD_WRITE)
02836     {
02837         AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_SEND;
02838     }
02839 
02840     if (lNetworkEvents & FD_OOB)
02841     {
02842         AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_OOB_RECEIVE;
02843     }
02844 
02845     if (lNetworkEvents & FD_ACCEPT)
02846     {
02847         AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_ACCEPT;
02848     }
02849 
02850     /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */
02851     if (lNetworkEvents & FD_CONNECT)
02852     {
02853         AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_CONNECT | AFD_EVENT_CONNECT_FAIL;
02854     }
02855 
02856     if (lNetworkEvents & FD_CLOSE)
02857     {
02858         AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_DISCONNECT | AFD_EVENT_ABORT | AFD_EVENT_CLOSE;
02859     }
02860 
02861     if (lNetworkEvents & FD_QOS)
02862     {
02863         AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_QOS;
02864     }
02865 
02866     if (lNetworkEvents & FD_GROUP_QOS)
02867     {
02868         AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_GROUP_QOS;
02869     }
02870 
02871     /* Send IOCTL */
02872     Status = NtDeviceIoControlFile (SockAsyncHelperAfdHandle,
02873                                     NULL,
02874                                     NULL,
02875                                     AsyncData,
02876                                     &AsyncData->IoStatusBlock,
02877                                     IOCTL_AFD_SELECT,
02878                                     &AsyncData->AsyncSelectInfo,
02879                                     sizeof(AsyncData->AsyncSelectInfo),
02880                                     &AsyncData->AsyncSelectInfo,
02881                                     sizeof(AsyncData->AsyncSelectInfo));
02882 
02883     /* I/O Manager Won't call the completion routine, let's do it manually */
02884     if (NT_SUCCESS(Status))
02885     {
02886         return;
02887     }
02888     else
02889     {
02890         AsyncData->IoStatusBlock.Status = Status;
02891         SockAsyncSelectCompletionRoutine(AsyncData, &AsyncData->IoStatusBlock);
02892     }
02893 }
02894 
02895 VOID SockProcessQueuedAsyncSelect(PVOID Context, PIO_STATUS_BLOCK IoStatusBlock)
02896 {
02897     PASYNC_DATA AsyncData = Context;
02898     BOOL FreeContext = TRUE;
02899     PSOCKET_INFORMATION Socket;
02900 
02901     /* Get the Socket */
02902     Socket = AsyncData->ParentSocket;
02903 
02904     /* If someone closed it, stop the function */
02905     if (Socket->SharedData.State != SocketClosed)
02906     {
02907         /* Check if the Sequence Number changed by now, in which case quit */
02908         if (AsyncData->SequenceNumber == Socket->SharedData.SequenceNumber)
02909         {
02910             /* Do the actuall select, if needed */
02911             if ((Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents)))
02912             {
02913                 SockProcessAsyncSelect(Socket, AsyncData);
02914                 FreeContext = FALSE;
02915             }
02916         }
02917     }
02918 
02919     /* Free the Context */
02920     if (FreeContext)
02921     {
02922         HeapFree(GetProcessHeap(), 0, AsyncData);
02923     }
02924 
02925     return;
02926 }
02927 
02928 VOID
02929 SockReenableAsyncSelectEvent (IN PSOCKET_INFORMATION Socket,
02930                               IN ULONG Event)
02931 {
02932     PASYNC_DATA AsyncData;
02933 
02934     /* Make sure the event is actually disabled */
02935     if (!(Socket->SharedData.AsyncDisabledEvents & Event))
02936     {
02937         return;
02938     }
02939 
02940     /* Re-enable it */
02941     Socket->SharedData.AsyncDisabledEvents &= ~Event;
02942 
02943     /* Return if no more events are being polled */
02944     if ((Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents)) == 0 )
02945     {
02946         return;
02947     }
02948 
02949     /* Wait on new events */
02950     AsyncData = HeapAlloc(GetProcessHeap(), 0, sizeof(ASYNC_DATA));
02951     if (!AsyncData) return;
02952 
02953     /* Create the Asynch Thread if Needed */
02954     SockCreateOrReferenceAsyncThread();
02955 
02956     /* Increase the sequence number to stop anything else */
02957     Socket->SharedData.SequenceNumber++;
02958 
02959     /* Set up the Async Data */
02960     AsyncData->ParentSocket = Socket;
02961     AsyncData->SequenceNumber = Socket->SharedData.SequenceNumber;
02962 
02963     /* Begin Async Select by using I/O Completion */
02964     NtSetIoCompletion(SockAsyncCompletionPort,
02965                      (PVOID)&SockProcessQueuedAsyncSelect,
02966                      AsyncData,
02967                      0,
02968                      0);
02969 
02970     /* All done */
02971     return;
02972 }
02973 
02974 BOOL
02975 WINAPI
02976 DllMain(HANDLE hInstDll,
02977         ULONG dwReason,
02978         PVOID Reserved)
02979 {
02980 
02981     switch (dwReason)
02982     {
02983     case DLL_PROCESS_ATTACH:
02984 
02985         AFD_DbgPrint(MAX_TRACE, ("Loading MSAFD.DLL \n"));
02986 
02987         /* Don't need thread attach notifications
02988         so disable them to improve performance */
02989         DisableThreadLibraryCalls(hInstDll);
02990 
02991         /* List of DLL Helpers */
02992         InitializeListHead(&SockHelpersListHead);
02993 
02994         /* Heap to use when allocating */
02995         GlobalHeap = GetProcessHeap();
02996 
02997         /* Initialize the lock that protects our socket list */
02998         InitializeCriticalSection(&SocketListLock);
02999 
03000         AFD_DbgPrint(MAX_TRACE, ("MSAFD.DLL has been loaded\n"));
03001 
03002         break;
03003 
03004     case DLL_THREAD_ATTACH:
03005         break;
03006 
03007     case DLL_THREAD_DETACH:
03008         break;
03009 
03010     case DLL_PROCESS_DETACH:
03011 
03012         /* Delete the socket list lock */
03013         DeleteCriticalSection(&SocketListLock);
03014 
03015         break;
03016     }
03017 
03018     AFD_DbgPrint(MAX_TRACE, ("DllMain of msafd.dll (leaving)\n"));
03019 
03020     return TRUE;
03021 }
03022 
03023 /* EOF */
03024 
03025 

Generated on Fri May 25 2012 04:20:41 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.