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