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