xref: /reactos/dll/win32/msafd/misc/dllmain.c (revision 53221834)
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(ULONG);
2642                     break;
2643 
2644                 case SO_SNDBUF:
2645                     Buffer = &Socket->SharedData->SizeOfSendBuffer;
2646                     BufferSize = sizeof(ULONG);
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(ULONG))
2864               {
2865                   if (lpErrno) *lpErrno = WSAEFAULT;
2866                   return SOCKET_ERROR;
2867               }
2868 
2869               SetSocketInformation(Socket,
2870                                    AFD_INFO_SEND_WINDOW_SIZE,
2871                                    NULL,
2872                                    (PULONG)optval,
2873                                    NULL,
2874                                    NULL,
2875                                    NULL);
2876               GetSocketInformation(Socket,
2877                                    AFD_INFO_SEND_WINDOW_SIZE,
2878                                    NULL,
2879                                    &Socket->SharedData->SizeOfSendBuffer,
2880                                    NULL,
2881                                    NULL,
2882                                    NULL);
2883 
2884               return NO_ERROR;
2885 
2886            case SO_RCVBUF:
2887               if (optlen < sizeof(ULONG))
2888               {
2889                   if (lpErrno) *lpErrno = WSAEFAULT;
2890                   return SOCKET_ERROR;
2891               }
2892 
2893               /* FIXME: We should not have to limit the packet receive buffer size like this. workaround for CORE-15804 */
2894               if (*(PULONG)optval > 0x2000)
2895                   *(PULONG)optval = 0x2000;
2896 
2897               SetSocketInformation(Socket,
2898                                    AFD_INFO_RECEIVE_WINDOW_SIZE,
2899                                    NULL,
2900                                    (PULONG)optval,
2901                                    NULL,
2902                                    NULL,
2903                                    NULL);
2904               GetSocketInformation(Socket,
2905                                    AFD_INFO_RECEIVE_WINDOW_SIZE,
2906                                    NULL,
2907                                    &Socket->SharedData->SizeOfRecvBuffer,
2908                                    NULL,
2909                                    NULL,
2910                                    NULL);
2911 
2912               return NO_ERROR;
2913 
2914            case SO_ERROR:
2915               if (optlen < sizeof(INT))
2916               {
2917                   if (lpErrno) *lpErrno = WSAEFAULT;
2918                   return SOCKET_ERROR;
2919               }
2920 
2921               RtlCopyMemory(&Socket->SharedData->SocketLastError,
2922                             optval,
2923                             sizeof(INT));
2924               return NO_ERROR;
2925 
2926            case SO_SNDTIMEO:
2927               if (optlen < sizeof(DWORD))
2928               {
2929                   if (lpErrno) *lpErrno = WSAEFAULT;
2930                   return SOCKET_ERROR;
2931               }
2932 
2933               RtlCopyMemory(&Socket->SharedData->SendTimeout,
2934                             optval,
2935                             sizeof(DWORD));
2936               return NO_ERROR;
2937 
2938            case SO_RCVTIMEO:
2939               if (optlen < sizeof(DWORD))
2940               {
2941                   if (lpErrno) *lpErrno = WSAEFAULT;
2942                   return SOCKET_ERROR;
2943               }
2944 
2945               RtlCopyMemory(&Socket->SharedData->RecvTimeout,
2946                             optval,
2947                             sizeof(DWORD));
2948               return NO_ERROR;
2949 
2950            case SO_KEEPALIVE:
2951            case SO_DONTROUTE:
2952               /* These go directly to the helper dll */
2953               goto SendToHelper;
2954 
2955            default:
2956               /* Obviously this is a hack */
2957               ERR("MSAFD: Set unknown optname %x\n", optname);
2958               return NO_ERROR;
2959         }
2960     }
2961 
2962 SendToHelper:
2963     Errno = Socket->HelperData->WSHSetSocketInformation(Socket->HelperContext,
2964                                                         s,
2965                                                         Socket->TdiAddressHandle,
2966                                                         Socket->TdiConnectionHandle,
2967                                                         level,
2968                                                         optname,
2969                                                         (PCHAR)optval,
2970                                                         optlen);
2971     if (lpErrno) *lpErrno = Errno;
2972     return (Errno == NO_ERROR) ? NO_ERROR : SOCKET_ERROR;
2973 }
2974 
2975 /*
2976  * FUNCTION: Initialize service provider for a client
2977  * ARGUMENTS:
2978  *     wVersionRequested = Highest WinSock SPI version that the caller can use
2979  *     lpWSPData         = Address of WSPDATA structure to initialize
2980  *     lpProtocolInfo    = Pointer to structure that defines the desired protocol
2981  *     UpcallTable       = Pointer to upcall table of the WinSock DLL
2982  *     lpProcTable       = Address of procedure table to initialize
2983  * RETURNS:
2984  *     Status of operation
2985  */
2986 _Must_inspect_result_
2987 int
2988 WSPAPI
2989 WSPStartup(
2990     _In_ WORD wVersionRequested,
2991     _In_ LPWSPDATA lpWSPData,
2992     _In_ LPWSAPROTOCOL_INFOW lpProtocolInfo,
2993     _In_ WSPUPCALLTABLE UpcallTable,
2994     _Out_ LPWSPPROC_TABLE lpProcTable)
2995 {
2996     NTSTATUS Status;
2997 
2998     if (((LOBYTE(wVersionRequested) == 2) && (HIBYTE(wVersionRequested) < 2)) ||
2999         (LOBYTE(wVersionRequested) < 2))
3000     {
3001         ERR("WSPStartup NOT SUPPORTED for version 0x%X\n", wVersionRequested);
3002         return WSAVERNOTSUPPORTED;
3003     }
3004     else
3005         Status = NO_ERROR;
3006     /* FIXME: Enable all cases of WSPStartup status */
3007     Upcalls = UpcallTable;
3008 
3009     if (Status == NO_ERROR)
3010     {
3011         lpProcTable->lpWSPAccept = WSPAccept;
3012         lpProcTable->lpWSPAddressToString = WSPAddressToString;
3013         lpProcTable->lpWSPAsyncSelect = WSPAsyncSelect;
3014         lpProcTable->lpWSPBind = WSPBind;
3015         lpProcTable->lpWSPCancelBlockingCall = WSPCancelBlockingCall;
3016         lpProcTable->lpWSPCleanup = WSPCleanup;
3017         lpProcTable->lpWSPCloseSocket = WSPCloseSocket;
3018         lpProcTable->lpWSPConnect = WSPConnect;
3019         lpProcTable->lpWSPDuplicateSocket = WSPDuplicateSocket;
3020         lpProcTable->lpWSPEnumNetworkEvents = WSPEnumNetworkEvents;
3021         lpProcTable->lpWSPEventSelect = WSPEventSelect;
3022         lpProcTable->lpWSPGetOverlappedResult = WSPGetOverlappedResult;
3023         lpProcTable->lpWSPGetPeerName = WSPGetPeerName;
3024         lpProcTable->lpWSPGetSockName = WSPGetSockName;
3025         lpProcTable->lpWSPGetSockOpt = WSPGetSockOpt;
3026         lpProcTable->lpWSPGetQOSByName = WSPGetQOSByName;
3027         lpProcTable->lpWSPIoctl = WSPIoctl;
3028         lpProcTable->lpWSPJoinLeaf = WSPJoinLeaf;
3029         lpProcTable->lpWSPListen = WSPListen;
3030         lpProcTable->lpWSPRecv = WSPRecv;
3031         lpProcTable->lpWSPRecvDisconnect = WSPRecvDisconnect;
3032         lpProcTable->lpWSPRecvFrom = WSPRecvFrom;
3033         lpProcTable->lpWSPSelect = WSPSelect;
3034         lpProcTable->lpWSPSend = WSPSend;
3035         lpProcTable->lpWSPSendDisconnect = WSPSendDisconnect;
3036         lpProcTable->lpWSPSendTo = WSPSendTo;
3037         lpProcTable->lpWSPSetSockOpt = WSPSetSockOpt;
3038         lpProcTable->lpWSPShutdown = WSPShutdown;
3039         lpProcTable->lpWSPSocket = WSPSocket;
3040         lpProcTable->lpWSPStringToAddress = WSPStringToAddress;
3041         lpWSPData->wVersion     = MAKEWORD(2, 2);
3042         lpWSPData->wHighVersion = MAKEWORD(2, 2);
3043         /* Save CatalogEntryId for all upcalls */
3044         CatalogEntryId = lpProtocolInfo->dwCatalogEntryId;
3045     }
3046 
3047     TRACE("Status (%d).\n", Status);
3048     return Status;
3049 }
3050 
3051 
3052 INT
3053 WSPAPI
3054 WSPAddressToString(IN LPSOCKADDR lpsaAddress,
3055                    IN DWORD dwAddressLength,
3056                    IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
3057                    OUT LPWSTR lpszAddressString,
3058                    IN OUT LPDWORD lpdwAddressStringLength,
3059                    OUT LPINT lpErrno)
3060 {
3061     SIZE_T size;
3062     WCHAR buffer[54]; /* 32 digits + 7':' + '[' + '%" + 5 digits + ']:' + 5 digits + '\0' */
3063     WCHAR *p;
3064 
3065     if (!lpsaAddress || !lpszAddressString || !lpdwAddressStringLength)
3066     {
3067         if (lpErrno) *lpErrno = WSAEFAULT;
3068         return SOCKET_ERROR;
3069     }
3070 
3071     switch (lpsaAddress->sa_family)
3072     {
3073         case AF_INET:
3074             if (dwAddressLength < sizeof(SOCKADDR_IN))
3075             {
3076                 if (lpErrno) *lpErrno = WSAEINVAL;
3077                 return SOCKET_ERROR;
3078             }
3079             swprintf(buffer,
3080                      L"%u.%u.%u.%u:%u",
3081                      (unsigned int)(ntohl(((SOCKADDR_IN *)lpsaAddress)->sin_addr.s_addr) >> 24 & 0xff),
3082                      (unsigned int)(ntohl(((SOCKADDR_IN *)lpsaAddress)->sin_addr.s_addr) >> 16 & 0xff),
3083                      (unsigned int)(ntohl(((SOCKADDR_IN *)lpsaAddress)->sin_addr.s_addr) >> 8 & 0xff),
3084                      (unsigned int)(ntohl(((SOCKADDR_IN *)lpsaAddress)->sin_addr.s_addr) & 0xff),
3085                      ntohs(((SOCKADDR_IN *)lpsaAddress)->sin_port));
3086 
3087             p = wcschr(buffer, L':');
3088             if (!((SOCKADDR_IN *)lpsaAddress)->sin_port)
3089             {
3090                 *p = 0;
3091             }
3092             break;
3093         default:
3094             if (lpErrno) *lpErrno = WSAEINVAL;
3095             return SOCKET_ERROR;
3096     }
3097 
3098     size = wcslen(buffer) + 1;
3099 
3100     if (*lpdwAddressStringLength < size)
3101     {
3102         *lpdwAddressStringLength = size;
3103         if (lpErrno) *lpErrno = WSAEFAULT;
3104         return SOCKET_ERROR;
3105     }
3106 
3107     *lpdwAddressStringLength = size;
3108     wcscpy(lpszAddressString, buffer);
3109     return 0;
3110 }
3111 
3112 INT
3113 WSPAPI
3114 WSPStringToAddress(IN LPWSTR AddressString,
3115                    IN INT AddressFamily,
3116                    IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
3117                    OUT LPSOCKADDR lpAddress,
3118                    IN OUT LPINT lpAddressLength,
3119                    OUT LPINT lpErrno)
3120 {
3121     int numdots = 0;
3122     USHORT port;
3123     LONG inetaddr = 0, ip_part;
3124     LPWSTR *bp = NULL;
3125     SOCKADDR_IN *sockaddr;
3126 
3127     if (!lpAddressLength || !lpAddress || !AddressString)
3128     {
3129         if (lpErrno) *lpErrno = WSAEINVAL;
3130         return SOCKET_ERROR;
3131     }
3132 
3133     sockaddr = (SOCKADDR_IN *)lpAddress;
3134 
3135     /* Set right address family */
3136     if (lpProtocolInfo != NULL)
3137     {
3138         sockaddr->sin_family = lpProtocolInfo->iAddressFamily;
3139     }
3140     else
3141     {
3142         sockaddr->sin_family = AddressFamily;
3143     }
3144 
3145     /* Report size */
3146     if (AddressFamily == AF_INET)
3147     {
3148         if (*lpAddressLength < (INT)sizeof(SOCKADDR_IN))
3149         {
3150             if (lpErrno) *lpErrno = WSAEFAULT;
3151         }
3152         else
3153         {
3154             // translate ip string to ip
3155 
3156             /* Get ip number */
3157             bp = &AddressString;
3158             inetaddr = 0;
3159 
3160             while (*bp < &AddressString[wcslen(AddressString)])
3161             {
3162                 ip_part = wcstol(*bp, bp, 10);
3163                 /* ip part number should be in range 0-255 */
3164                 if (ip_part < 0 || ip_part > 255)
3165                 {
3166                     if (lpErrno) *lpErrno = WSAEINVAL;
3167                     return SOCKET_ERROR;
3168                 }
3169                 inetaddr = (inetaddr << 8) + ip_part;
3170                 /* we end on string end or port separator */
3171                 if ((*bp)[0] == 0 || (*bp)[0] == L':')
3172                     break;
3173                 /* ip parts are dot separated. verify it */
3174                 if ((*bp)[0] != L'.')
3175                 {
3176                     if (lpErrno) *lpErrno = WSAEINVAL;
3177                     return SOCKET_ERROR;
3178                 }
3179                 /* count the dots */
3180                 numdots++;
3181                 /* move over the dot to next ip part */
3182                 (*bp)++;
3183             }
3184 
3185             /* check dots count */
3186             if (numdots != 3)
3187             {
3188                 if (lpErrno) *lpErrno = WSAEINVAL;
3189                 return SOCKET_ERROR;
3190             }
3191 
3192             /* Get port number */
3193             if ((*bp)[0] == L':')
3194             {
3195                 /* move over the column to port part */
3196                 (*bp)++;
3197                 /* next char should be numeric */
3198                 if ((*bp)[0] < L'0' || (*bp)[0] > L'9')
3199                 {
3200                     if (lpErrno) *lpErrno = WSAEINVAL;
3201                     return SOCKET_ERROR;
3202                 }
3203                 port = wcstol(*bp, bp, 10);
3204             }
3205             else
3206             {
3207                 port = 0;
3208             }
3209 
3210             if (lpErrno) *lpErrno = NO_ERROR;
3211             /* rest sockaddr.sin_addr.s_addr
3212             for we need to be sure it is zero when we come to while */
3213             *lpAddressLength = sizeof(*sockaddr);
3214             memset(lpAddress, 0, sizeof(*sockaddr));
3215             sockaddr->sin_family = AF_INET;
3216             sockaddr->sin_addr.s_addr = inetaddr;
3217             sockaddr->sin_port = port;
3218         }
3219     }
3220 
3221     if (lpErrno && !*lpErrno)
3222     {
3223         return 0;
3224     }
3225 
3226     return SOCKET_ERROR;
3227 }
3228 
3229 /*
3230  * FUNCTION: Cleans up service provider for a client
3231  * ARGUMENTS:
3232  *     lpErrno = Address of buffer for error information
3233  * RETURNS:
3234  *     0 if successful, or SOCKET_ERROR if not
3235  */
3236 INT
3237 WSPAPI
3238 WSPCleanup(OUT LPINT lpErrno)
3239 
3240 {
3241     TRACE("Leaving.\n");
3242 
3243     if (lpErrno) *lpErrno = NO_ERROR;
3244 
3245     return 0;
3246 }
3247 
3248 VOID
3249 NTAPI
3250 AfdInfoAPC(PVOID ApcContext,
3251     PIO_STATUS_BLOCK IoStatusBlock,
3252     ULONG Reserved)
3253 {
3254     PAFDAPCCONTEXT Context = ApcContext;
3255 
3256     Context->lpCompletionRoutine(IoStatusBlock->Status, IoStatusBlock->Information, Context->lpOverlapped, 0);
3257     HeapFree(GlobalHeap, 0, ApcContext);
3258 }
3259 
3260 int
3261 GetSocketInformation(PSOCKET_INFORMATION Socket,
3262                      ULONG AfdInformationClass,
3263                      PBOOLEAN Boolean OPTIONAL,
3264                      PULONG Ulong OPTIONAL,
3265                      PLARGE_INTEGER LargeInteger OPTIONAL,
3266                      LPWSAOVERLAPPED Overlapped OPTIONAL,
3267                      LPWSAOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine OPTIONAL)
3268 {
3269     PIO_STATUS_BLOCK    IOSB;
3270     IO_STATUS_BLOCK     DummyIOSB;
3271     AFD_INFO            InfoData;
3272     NTSTATUS            Status;
3273     PAFDAPCCONTEXT      APCContext;
3274     PIO_APC_ROUTINE     APCFunction;
3275     HANDLE              Event = NULL;
3276     HANDLE              SockEvent;
3277 
3278     Status = NtCreateEvent(&SockEvent,
3279                            EVENT_ALL_ACCESS,
3280                            NULL,
3281                            SynchronizationEvent,
3282                            FALSE);
3283 
3284     if( !NT_SUCCESS(Status) )
3285         return SOCKET_ERROR;
3286 
3287     /* Set Info Class */
3288     InfoData.InformationClass = AfdInformationClass;
3289 
3290     /* Verify if we should use APC */
3291     if (Overlapped == NULL)
3292     {
3293         /* Not using Overlapped structure, so use normal blocking on event */
3294         APCContext = NULL;
3295         APCFunction = NULL;
3296         Event = SockEvent;
3297         IOSB = &DummyIOSB;
3298     }
3299     else
3300     {
3301         /* Overlapped request for non overlapped opened socket */
3302         if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0)
3303         {
3304             TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
3305             NtClose( SockEvent );
3306             return 0;
3307         }
3308         if (CompletionRoutine == NULL)
3309         {
3310             /* Using Overlapped Structure, but no Completition Routine, so no need for APC */
3311             APCContext = (PAFDAPCCONTEXT)Overlapped;
3312             APCFunction = NULL;
3313             Event = Overlapped->hEvent;
3314         }
3315         else
3316         {
3317             /* Using Overlapped Structure and a Completition Routine, so use an APC */
3318             APCFunction = &AfdInfoAPC; // should be a private io completition function inside us
3319             APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT));
3320             if (!APCContext)
3321             {
3322                 ERR("Not enough memory for APC Context\n");
3323                 NtClose( SockEvent );
3324                 return WSAEFAULT;
3325             }
3326             APCContext->lpCompletionRoutine = CompletionRoutine;
3327             APCContext->lpOverlapped = Overlapped;
3328             APCContext->lpSocket = Socket;
3329         }
3330 
3331         IOSB = (PIO_STATUS_BLOCK)&Overlapped->Internal;
3332     }
3333 
3334     IOSB->Status = STATUS_PENDING;
3335 
3336     /* Send IOCTL */
3337     Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
3338                                    Event,
3339                                    APCFunction,
3340                                    APCContext,
3341                                    IOSB,
3342                                    IOCTL_AFD_GET_INFO,
3343                                    &InfoData,
3344                                    sizeof(InfoData),
3345                                    &InfoData,
3346                                    sizeof(InfoData));
3347 
3348     /* Wait for return */
3349     if (Status == STATUS_PENDING && Overlapped == NULL)
3350     {
3351         WaitForSingleObject(SockEvent, INFINITE);
3352         Status = IOSB->Status;
3353     }
3354 
3355     NtClose( SockEvent );
3356 
3357     TRACE("Status %x Information %d\n", Status, IOSB->Information);
3358 
3359     if (Status == STATUS_PENDING)
3360     {
3361         TRACE("Leaving (Pending)\n");
3362         return WSA_IO_PENDING;
3363     }
3364 
3365     if (Status != STATUS_SUCCESS)
3366         return SOCKET_ERROR;
3367 
3368     /* Return Information */
3369     if (Ulong != NULL)
3370     {
3371         *Ulong = InfoData.Information.Ulong;
3372     }
3373     if (LargeInteger != NULL)
3374     {
3375         *LargeInteger = InfoData.Information.LargeInteger;
3376     }
3377     if (Boolean != NULL)
3378     {
3379         *Boolean = InfoData.Information.Boolean;
3380     }
3381 
3382     return NO_ERROR;
3383 
3384 }
3385 
3386 
3387 int
3388 SetSocketInformation(PSOCKET_INFORMATION Socket,
3389                      ULONG AfdInformationClass,
3390                      PBOOLEAN Boolean OPTIONAL,
3391                      PULONG Ulong OPTIONAL,
3392                      PLARGE_INTEGER LargeInteger OPTIONAL,
3393                      LPWSAOVERLAPPED Overlapped OPTIONAL,
3394                      LPWSAOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine OPTIONAL)
3395 {
3396     PIO_STATUS_BLOCK    IOSB;
3397     IO_STATUS_BLOCK     DummyIOSB;
3398     AFD_INFO            InfoData;
3399     NTSTATUS            Status;
3400     PAFDAPCCONTEXT      APCContext;
3401     PIO_APC_ROUTINE     APCFunction;
3402     HANDLE              Event = NULL;
3403     HANDLE              SockEvent;
3404 
3405     Status = NtCreateEvent(&SockEvent,
3406                            EVENT_ALL_ACCESS,
3407                            NULL,
3408                            SynchronizationEvent,
3409                            FALSE);
3410 
3411     if( !NT_SUCCESS(Status) )
3412         return SOCKET_ERROR;
3413 
3414     /* Set Info Class */
3415     InfoData.InformationClass = AfdInformationClass;
3416 
3417     /* Set Information */
3418     if (Ulong != NULL)
3419     {
3420         InfoData.Information.Ulong = *Ulong;
3421     }
3422     if (LargeInteger != NULL)
3423     {
3424         InfoData.Information.LargeInteger = *LargeInteger;
3425     }
3426     if (Boolean != NULL)
3427     {
3428         InfoData.Information.Boolean = *Boolean;
3429     }
3430 
3431     /* Verify if we should use APC */
3432     if (Overlapped == NULL)
3433     {
3434         /* Not using Overlapped structure, so use normal blocking on event */
3435         APCContext = NULL;
3436         APCFunction = NULL;
3437         Event = SockEvent;
3438         IOSB = &DummyIOSB;
3439     }
3440     else
3441     {
3442         /* Overlapped request for non overlapped opened socket */
3443         if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0)
3444         {
3445             TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
3446             NtClose( SockEvent );
3447             return 0;
3448         }
3449         if (CompletionRoutine == NULL)
3450         {
3451             /* Using Overlapped Structure, but no Completition Routine, so no need for APC */
3452             APCContext = (PAFDAPCCONTEXT)Overlapped;
3453             APCFunction = NULL;
3454             Event = Overlapped->hEvent;
3455         }
3456         else
3457         {
3458             /* Using Overlapped Structure and a Completition Routine, so use an APC */
3459             APCFunction = &AfdInfoAPC; // should be a private io completition function inside us
3460             APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT));
3461             if (!APCContext)
3462             {
3463                 ERR("Not enough memory for APC Context\n");
3464                 NtClose( SockEvent );
3465                 return WSAEFAULT;
3466             }
3467             APCContext->lpCompletionRoutine = CompletionRoutine;
3468             APCContext->lpOverlapped = Overlapped;
3469             APCContext->lpSocket = Socket;
3470         }
3471 
3472         IOSB = (PIO_STATUS_BLOCK)&Overlapped->Internal;
3473     }
3474 
3475     IOSB->Status = STATUS_PENDING;
3476 
3477     /* Send IOCTL */
3478     Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
3479                                    Event,
3480                                    APCFunction,
3481                                    APCContext,
3482                                    IOSB,
3483                                    IOCTL_AFD_SET_INFO,
3484                                    &InfoData,
3485                                    sizeof(InfoData),
3486                                    NULL,
3487                                    0);
3488 
3489     /* Wait for return */
3490     if (Status == STATUS_PENDING && Overlapped == NULL)
3491     {
3492         WaitForSingleObject(SockEvent, INFINITE);
3493         Status = IOSB->Status;
3494     }
3495 
3496     NtClose( SockEvent );
3497 
3498     TRACE("Status %x Information %d\n", Status, IOSB->Information);
3499 
3500     if (Status == STATUS_PENDING)
3501     {
3502         TRACE("Leaving (Pending)\n");
3503         return WSA_IO_PENDING;
3504     }
3505 
3506     return Status == STATUS_SUCCESS ? NO_ERROR : SOCKET_ERROR;
3507 
3508 }
3509 
3510 PSOCKET_INFORMATION
3511 GetSocketStructure(SOCKET Handle)
3512 {
3513     PSOCKET_INFORMATION CurrentSocket;
3514 
3515     EnterCriticalSection(&SocketListLock);
3516 
3517     CurrentSocket = SocketListHead;
3518     while (CurrentSocket)
3519     {
3520         if (CurrentSocket->Handle == Handle)
3521         {
3522             LeaveCriticalSection(&SocketListLock);
3523             return CurrentSocket;
3524         }
3525 
3526         CurrentSocket = CurrentSocket->NextSocket;
3527     }
3528 
3529     LeaveCriticalSection(&SocketListLock);
3530 
3531     return NULL;
3532 }
3533 
3534 int CreateContext(PSOCKET_INFORMATION Socket)
3535 {
3536     IO_STATUS_BLOCK     IOSB;
3537     SOCKET_CONTEXT      ContextData;
3538     NTSTATUS            Status;
3539     HANDLE              SockEvent;
3540 
3541     Status = NtCreateEvent(&SockEvent,
3542                            EVENT_ALL_ACCESS,
3543                            NULL,
3544                            SynchronizationEvent,
3545                            FALSE);
3546 
3547     if( !NT_SUCCESS(Status) )
3548         return SOCKET_ERROR;
3549 
3550     /* Create Context */
3551     ContextData.SharedData = *Socket->SharedData;
3552     ContextData.SizeOfHelperData = 0;
3553     RtlCopyMemory (&ContextData.LocalAddress,
3554                    Socket->LocalAddress,
3555                    Socket->SharedData->SizeOfLocalAddress);
3556     RtlCopyMemory (&ContextData.RemoteAddress,
3557                    Socket->RemoteAddress,
3558                    Socket->SharedData->SizeOfRemoteAddress);
3559 
3560     /* Send IOCTL */
3561     Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
3562                                    SockEvent,
3563                                    NULL,
3564                                    NULL,
3565                                    &IOSB,
3566                                    IOCTL_AFD_SET_CONTEXT,
3567                                    &ContextData,
3568                                    sizeof(ContextData),
3569                                    NULL,
3570                                    0);
3571 
3572     /* Wait for Completion */
3573     if (Status == STATUS_PENDING)
3574     {
3575         WaitForSingleObject(SockEvent, INFINITE);
3576         Status = IOSB.Status;
3577     }
3578 
3579     NtClose( SockEvent );
3580 
3581     return Status == STATUS_SUCCESS ? NO_ERROR : SOCKET_ERROR;
3582 }
3583 
3584 BOOLEAN SockCreateOrReferenceAsyncThread(VOID)
3585 {
3586     HANDLE hAsyncThread;
3587     DWORD AsyncThreadId;
3588     HANDLE AsyncEvent;
3589     OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags;
3590     NTSTATUS Status;
3591 
3592     /* Check if the Thread Already Exists */
3593     if (SockAsyncThreadRefCount)
3594     {
3595         ASSERT(SockAsyncCompletionPort);
3596         return TRUE;
3597     }
3598 
3599     /* Create the Completion Port */
3600     if (!SockAsyncCompletionPort)
3601     {
3602         Status = NtCreateIoCompletion(&SockAsyncCompletionPort,
3603                                       IO_COMPLETION_ALL_ACCESS,
3604                                       NULL,
3605                                       2); // Allow 2 threads only
3606         if (!NT_SUCCESS(Status))
3607         {
3608              ERR("Failed to create completion port: 0x%08x\n", Status);
3609              return FALSE;
3610         }
3611         /* Protect Handle */
3612         HandleFlags.ProtectFromClose = TRUE;
3613         HandleFlags.Inherit = FALSE;
3614         Status = NtSetInformationObject(SockAsyncCompletionPort,
3615                                         ObjectHandleFlagInformation,
3616                                         &HandleFlags,
3617                                         sizeof(HandleFlags));
3618     }
3619 
3620     /* Create the Async Event */
3621     Status = NtCreateEvent(&AsyncEvent,
3622                            EVENT_ALL_ACCESS,
3623                            NULL,
3624                            NotificationEvent,
3625                            FALSE);
3626 
3627     /* Create the Async Thread */
3628     hAsyncThread = CreateThread(NULL,
3629                                 0,
3630                                 SockAsyncThread,
3631                                 NULL,
3632                                 0,
3633                                 &AsyncThreadId);
3634 
3635     /* Close the Handle */
3636     NtClose(hAsyncThread);
3637 
3638     /* Increase the Reference Count */
3639     SockAsyncThreadRefCount++;
3640     return TRUE;
3641 }
3642 
3643 ULONG
3644 NTAPI
3645 SockAsyncThread(PVOID ThreadParam)
3646 {
3647     PVOID AsyncContext;
3648     PASYNC_COMPLETION_ROUTINE AsyncCompletionRoutine;
3649     IO_STATUS_BLOCK IOSB;
3650     NTSTATUS Status;
3651 
3652     /* Make the Thread Higher Priority */
3653     SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
3654 
3655     /* Do a KQUEUE/WorkItem Style Loop, thanks to IoCompletion Ports */
3656     do
3657     {
3658         Status =  NtRemoveIoCompletion (SockAsyncCompletionPort,
3659                                         (PVOID*)&AsyncCompletionRoutine,
3660                                         &AsyncContext,
3661                                         &IOSB,
3662                                         NULL);
3663         /* Call the Async Function */
3664         if (NT_SUCCESS(Status))
3665         {
3666             (*AsyncCompletionRoutine)(AsyncContext, &IOSB);
3667         }
3668         else
3669         {
3670             /* It Failed, sleep for a second */
3671             Sleep(1000);
3672         }
3673     } while ((Status != STATUS_TIMEOUT));
3674 
3675     /* The Thread has Ended */
3676     return 0;
3677 }
3678 
3679 BOOLEAN SockGetAsyncSelectHelperAfdHandle(VOID)
3680 {
3681     UNICODE_STRING AfdHelper;
3682     OBJECT_ATTRIBUTES ObjectAttributes;
3683     IO_STATUS_BLOCK IoSb;
3684     FILE_COMPLETION_INFORMATION CompletionInfo;
3685     OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags;
3686 
3687     /* First, make sure we're not already initialized */
3688     if (SockAsyncHelperAfdHandle)
3689     {
3690         return TRUE;
3691     }
3692 
3693     /* Set up Handle Name and Object */
3694     RtlInitUnicodeString(&AfdHelper, L"\\Device\\Afd\\AsyncSelectHlp" );
3695                          InitializeObjectAttributes(&ObjectAttributes,
3696                          &AfdHelper,
3697                          OBJ_INHERIT | OBJ_CASE_INSENSITIVE,
3698                          NULL,
3699                          NULL);
3700 
3701     /* Open the Handle to AFD */
3702     NtCreateFile(&SockAsyncHelperAfdHandle,
3703                  GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
3704                  &ObjectAttributes,
3705                  &IoSb,
3706                  NULL,
3707                  0,
3708                  FILE_SHARE_READ | FILE_SHARE_WRITE,
3709                  FILE_OPEN_IF,
3710                  0,
3711                  NULL,
3712                  0);
3713 
3714     /*
3715      * Now Set up the Completion Port Information
3716      * This means that whenever a Poll is finished, the routine will be executed
3717      */
3718     CompletionInfo.Port = SockAsyncCompletionPort;
3719     CompletionInfo.Key = SockAsyncSelectCompletionRoutine;
3720     NtSetInformationFile(SockAsyncHelperAfdHandle,
3721                          &IoSb,
3722                          &CompletionInfo,
3723                          sizeof(CompletionInfo),
3724                          FileCompletionInformation);
3725 
3726 
3727     /* Protect the Handle */
3728     HandleFlags.ProtectFromClose = TRUE;
3729     HandleFlags.Inherit = FALSE;
3730     NtSetInformationObject(SockAsyncCompletionPort,
3731                            ObjectHandleFlagInformation,
3732                            &HandleFlags,
3733                            sizeof(HandleFlags));
3734 
3735 
3736     /* Set this variable to true so that Send/Recv/Accept will know wether to renable disabled events */
3737     SockAsyncSelectCalled = TRUE;
3738     return TRUE;
3739 }
3740 
3741 VOID SockAsyncSelectCompletionRoutine(PVOID Context, PIO_STATUS_BLOCK IoStatusBlock)
3742 {
3743 
3744     PASYNC_DATA AsyncData = Context;
3745     PSOCKET_INFORMATION Socket;
3746     ULONG x;
3747 
3748     /* Get the Socket */
3749     Socket = AsyncData->ParentSocket;
3750 
3751     /* Check if the Sequence  Number Changed behind our back */
3752     if (AsyncData->SequenceNumber != Socket->SharedData->SequenceNumber )
3753     {
3754         return;
3755     }
3756 
3757     /* Check we were manually called b/c of a failure */
3758     if (!NT_SUCCESS(IoStatusBlock->Status))
3759     {
3760         /* FIXME: Perform Upcall */
3761         return;
3762     }
3763 
3764     for (x = 1; x; x<<=1)
3765     {
3766         switch (AsyncData->AsyncSelectInfo.Handles[0].Events & x)
3767         {
3768             case AFD_EVENT_RECEIVE:
3769                 if (0 != (Socket->SharedData->AsyncEvents & FD_READ) &&
3770                     0 == (Socket->SharedData->AsyncDisabledEvents & FD_READ))
3771                 {
3772                     /* Make the Notification */
3773                     (Upcalls.lpWPUPostMessage)(Socket->SharedData->hWnd,
3774                                                Socket->SharedData->wMsg,
3775                                                Socket->Handle,
3776                                                WSAMAKESELECTREPLY(FD_READ, 0));
3777                     /* Disable this event until the next read(); */
3778                     Socket->SharedData->AsyncDisabledEvents |= FD_READ;
3779                 }
3780             break;
3781 
3782             case AFD_EVENT_OOB_RECEIVE:
3783             if (0 != (Socket->SharedData->AsyncEvents & FD_OOB) &&
3784                 0 == (Socket->SharedData->AsyncDisabledEvents & FD_OOB))
3785             {
3786                 /* Make the Notification */
3787                 (Upcalls.lpWPUPostMessage)(Socket->SharedData->hWnd,
3788                                            Socket->SharedData->wMsg,
3789                                            Socket->Handle,
3790                                            WSAMAKESELECTREPLY(FD_OOB, 0));
3791                 /* Disable this event until the next read(); */
3792                 Socket->SharedData->AsyncDisabledEvents |= FD_OOB;
3793             }
3794             break;
3795 
3796             case AFD_EVENT_SEND:
3797                 if (0 != (Socket->SharedData->AsyncEvents & FD_WRITE) &&
3798                     0 == (Socket->SharedData->AsyncDisabledEvents & FD_WRITE))
3799                 {
3800                     /* Make the Notification */
3801                     (Upcalls.lpWPUPostMessage)(Socket->SharedData->hWnd,
3802                                                Socket->SharedData->wMsg,
3803                                                Socket->Handle,
3804                                                WSAMAKESELECTREPLY(FD_WRITE, 0));
3805                     /* Disable this event until the next write(); */
3806                     Socket->SharedData->AsyncDisabledEvents |= FD_WRITE;
3807                 }
3808                 break;
3809 
3810                 /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */
3811             case AFD_EVENT_CONNECT:
3812             case AFD_EVENT_CONNECT_FAIL:
3813                 if (0 != (Socket->SharedData->AsyncEvents & FD_CONNECT) &&
3814                     0 == (Socket->SharedData->AsyncDisabledEvents & FD_CONNECT))
3815                 {
3816                     /* Make the Notification */
3817                     (Upcalls.lpWPUPostMessage)(Socket->SharedData->hWnd,
3818                         Socket->SharedData->wMsg,
3819                         Socket->Handle,
3820                         WSAMAKESELECTREPLY(FD_CONNECT, 0));
3821                     /* Disable this event forever; */
3822                     Socket->SharedData->AsyncDisabledEvents |= FD_CONNECT;
3823                 }
3824                 break;
3825 
3826             case AFD_EVENT_ACCEPT:
3827                 if (0 != (Socket->SharedData->AsyncEvents & FD_ACCEPT) &&
3828                     0 == (Socket->SharedData->AsyncDisabledEvents & FD_ACCEPT))
3829                 {
3830                     /* Make the Notification */
3831                     (Upcalls.lpWPUPostMessage)(Socket->SharedData->hWnd,
3832                                                Socket->SharedData->wMsg,
3833                                                Socket->Handle,
3834                                                WSAMAKESELECTREPLY(FD_ACCEPT, 0));
3835                     /* Disable this event until the next accept(); */
3836                     Socket->SharedData->AsyncDisabledEvents |= FD_ACCEPT;
3837                 }
3838                 break;
3839 
3840             case AFD_EVENT_DISCONNECT:
3841             case AFD_EVENT_ABORT:
3842             case AFD_EVENT_CLOSE:
3843                 if (0 != (Socket->SharedData->AsyncEvents & FD_CLOSE) &&
3844                     0 == (Socket->SharedData->AsyncDisabledEvents & FD_CLOSE))
3845                 {
3846                     /* Make the Notification */
3847                     (Upcalls.lpWPUPostMessage)(Socket->SharedData->hWnd,
3848                                                Socket->SharedData->wMsg,
3849                                                Socket->Handle,
3850                                                WSAMAKESELECTREPLY(FD_CLOSE, 0));
3851                     /* Disable this event forever; */
3852                     Socket->SharedData->AsyncDisabledEvents |= FD_CLOSE;
3853                 }
3854                  break;
3855             /* FIXME: Support QOS */
3856         }
3857     }
3858 
3859     /* Check if there are any events left for us to check */
3860     if ((Socket->SharedData->AsyncEvents & (~Socket->SharedData->AsyncDisabledEvents)) == 0 )
3861     {
3862         return;
3863     }
3864 
3865     /* Keep Polling */
3866     SockProcessAsyncSelect(Socket, AsyncData);
3867     return;
3868 }
3869 
3870 VOID SockProcessAsyncSelect(PSOCKET_INFORMATION Socket, PASYNC_DATA AsyncData)
3871 {
3872 
3873     ULONG lNetworkEvents;
3874     NTSTATUS Status;
3875 
3876     /* Set up the Async Data Event Info */
3877     AsyncData->AsyncSelectInfo.Timeout.HighPart = 0x7FFFFFFF;
3878     AsyncData->AsyncSelectInfo.Timeout.LowPart = 0xFFFFFFFF;
3879     AsyncData->AsyncSelectInfo.HandleCount = 1;
3880     AsyncData->AsyncSelectInfo.Exclusive = TRUE;
3881     AsyncData->AsyncSelectInfo.Handles[0].Handle = Socket->Handle;
3882     AsyncData->AsyncSelectInfo.Handles[0].Events = 0;
3883 
3884     /* Remove unwanted events */
3885     lNetworkEvents = Socket->SharedData->AsyncEvents & (~Socket->SharedData->AsyncDisabledEvents);
3886 
3887     /* Set Events to wait for */
3888     if (lNetworkEvents & FD_READ)
3889     {
3890         AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_RECEIVE;
3891     }
3892 
3893     if (lNetworkEvents & FD_WRITE)
3894     {
3895         AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_SEND;
3896     }
3897 
3898     if (lNetworkEvents & FD_OOB)
3899     {
3900         AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_OOB_RECEIVE;
3901     }
3902 
3903     if (lNetworkEvents & FD_ACCEPT)
3904     {
3905         AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_ACCEPT;
3906     }
3907 
3908     /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */
3909     if (lNetworkEvents & FD_CONNECT)
3910     {
3911         AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_CONNECT | AFD_EVENT_CONNECT_FAIL;
3912     }
3913 
3914     if (lNetworkEvents & FD_CLOSE)
3915     {
3916         AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_DISCONNECT | AFD_EVENT_ABORT | AFD_EVENT_CLOSE;
3917     }
3918 
3919     if (lNetworkEvents & FD_QOS)
3920     {
3921         AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_QOS;
3922     }
3923 
3924     if (lNetworkEvents & FD_GROUP_QOS)
3925     {
3926         AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_GROUP_QOS;
3927     }
3928 
3929     /* Send IOCTL */
3930     Status = NtDeviceIoControlFile (SockAsyncHelperAfdHandle,
3931                                     NULL,
3932                                     NULL,
3933                                     AsyncData,
3934                                     &AsyncData->IoStatusBlock,
3935                                     IOCTL_AFD_SELECT,
3936                                     &AsyncData->AsyncSelectInfo,
3937                                     sizeof(AsyncData->AsyncSelectInfo),
3938                                     &AsyncData->AsyncSelectInfo,
3939                                     sizeof(AsyncData->AsyncSelectInfo));
3940 
3941     /* I/O Manager Won't call the completion routine, let's do it manually */
3942     if (NT_SUCCESS(Status))
3943     {
3944         return;
3945     }
3946     else
3947     {
3948         AsyncData->IoStatusBlock.Status = Status;
3949         SockAsyncSelectCompletionRoutine(AsyncData, &AsyncData->IoStatusBlock);
3950     }
3951 }
3952 
3953 VOID SockProcessQueuedAsyncSelect(PVOID Context, PIO_STATUS_BLOCK IoStatusBlock)
3954 {
3955     PASYNC_DATA AsyncData = Context;
3956     BOOL FreeContext = TRUE;
3957     PSOCKET_INFORMATION Socket;
3958 
3959     /* Get the Socket */
3960     Socket = AsyncData->ParentSocket;
3961 
3962     /* If someone closed it, stop the function */
3963     if (Socket->SharedData->State != SocketClosed)
3964     {
3965         /* Check if the Sequence Number changed by now, in which case quit */
3966         if (AsyncData->SequenceNumber == Socket->SharedData->SequenceNumber)
3967         {
3968             /* Do the actual select, if needed */
3969             if ((Socket->SharedData->AsyncEvents & (~Socket->SharedData->AsyncDisabledEvents)))
3970             {
3971                 SockProcessAsyncSelect(Socket, AsyncData);
3972                 FreeContext = FALSE;
3973             }
3974         }
3975     }
3976 
3977     /* Free the Context */
3978     if (FreeContext)
3979     {
3980         HeapFree(GetProcessHeap(), 0, AsyncData);
3981     }
3982 
3983     return;
3984 }
3985 
3986 VOID
3987 SockReenableAsyncSelectEvent (IN PSOCKET_INFORMATION Socket,
3988                               IN ULONG Event)
3989 {
3990     PASYNC_DATA AsyncData;
3991 
3992     /* Make sure the event is actually disabled */
3993     if (!(Socket->SharedData->AsyncDisabledEvents & Event))
3994     {
3995         return;
3996     }
3997 
3998     /* Re-enable it */
3999     Socket->SharedData->AsyncDisabledEvents &= ~Event;
4000 
4001     /* Return if no more events are being polled */
4002     if ((Socket->SharedData->AsyncEvents & (~Socket->SharedData->AsyncDisabledEvents)) == 0 )
4003     {
4004         return;
4005     }
4006 
4007     /* Wait on new events */
4008     AsyncData = HeapAlloc(GetProcessHeap(), 0, sizeof(ASYNC_DATA));
4009     if (!AsyncData) return;
4010 
4011     /* Create the Asynch Thread if Needed */
4012     SockCreateOrReferenceAsyncThread();
4013 
4014     /* Increase the sequence number to stop anything else */
4015     Socket->SharedData->SequenceNumber++;
4016 
4017     /* Set up the Async Data */
4018     AsyncData->ParentSocket = Socket;
4019     AsyncData->SequenceNumber = Socket->SharedData->SequenceNumber;
4020 
4021     /* Begin Async Select by using I/O Completion */
4022     NtSetIoCompletion(SockAsyncCompletionPort,
4023                      (PVOID)&SockProcessQueuedAsyncSelect,
4024                      AsyncData,
4025                      0,
4026                      0);
4027 
4028     /* All done */
4029     return;
4030 }
4031 
4032 BOOL
4033 WINAPI
4034 DllMain(HANDLE hInstDll,
4035         ULONG dwReason,
4036         PVOID Reserved)
4037 {
4038 
4039     switch (dwReason)
4040     {
4041     case DLL_PROCESS_ATTACH:
4042 
4043         TRACE("Loading MSAFD.DLL \n");
4044 
4045         /* Don't need thread attach notifications
4046         so disable them to improve performance */
4047         DisableThreadLibraryCalls(hInstDll);
4048 
4049         /* List of DLL Helpers */
4050         InitializeListHead(&SockHelpersListHead);
4051 
4052         /* Heap to use when allocating */
4053         GlobalHeap = GetProcessHeap();
4054 
4055         /* Initialize the lock that protects our socket list */
4056         InitializeCriticalSection(&SocketListLock);
4057 
4058         TRACE("MSAFD.DLL has been loaded\n");
4059 
4060         break;
4061 
4062     case DLL_THREAD_ATTACH:
4063         break;
4064 
4065     case DLL_THREAD_DETACH:
4066         break;
4067 
4068     case DLL_PROCESS_DETACH:
4069 
4070         /* Delete the socket list lock */
4071         DeleteCriticalSection(&SocketListLock);
4072 
4073         break;
4074     }
4075 
4076     TRACE("DllMain of msafd.dll (leaving)\n");
4077 
4078     return TRUE;
4079 }
4080 
4081 /* EOF */
4082