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