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