ReactOS  0.4.14-dev-593-g1793dcc
dllmain.c
Go to the documentation of this file.
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 
21 DWORD CatalogEntryId; /* CatalogEntryId for upcalls */
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
49  int SocketType,
50  int Protocol,
51  LPWSAPROTOCOL_INFOW lpProtocolInfo,
52  GROUP g,
53  DWORD dwFlags,
54  LPINT lpErrno)
55 {
57  IO_STATUS_BLOCK IOSB;
58  USHORT SizeOfPacket;
59  ULONG SizeOfEA;
60  PAFD_CREATE_PACKET AfdPacket;
61  HANDLE Sock;
62  PSOCKET_INFORMATION Socket = NULL;
64  PHELPER_DATA HelperData;
65  PVOID HelperDLLContext;
66  DWORD HelperEvents;
67  UNICODE_STRING TransportName;
68  UNICODE_STRING DevName;
70  INT Status;
71  PSOCK_SHARED_INFO SharedData = NULL;
72 
73  TRACE("Creating Socket, getting TDI Name - AddressFamily (%d) SocketType (%d) Protocol (%d).\n",
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),
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)
114 
115  if (SocketType == 0)
116  {
117  switch (Protocol)
118  {
119  case IPPROTO_TCP:
121  break;
122  case IPPROTO_UDP:
124  break;
125  case IPPROTO_RAW:
127  break;
128  default:
129  TRACE("Unknown Protocol (%d). We will try SOCK_STREAM.\n", Protocol);
131  break;
132  }
133  }
134 
135  if (Protocol == 0)
136  {
137  switch (SocketType)
138  {
139  case SOCK_STREAM:
141  break;
142  case SOCK_DGRAM:
144  break;
145  case SOCK_RAW:
147  break;
148  default:
149  TRACE("Unknown SocketType (%d). We will try IPPROTO_TCP.\n", SocketType);
151  break;
152  }
153  }
154 
155  /* Get Helper Data and Transport */
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  {
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;
205  Socket->SharedData->SocketType = SocketType;
206  Socket->SharedData->Protocol = Protocol;
207  Socket->SharedData->SizeOfLocalAddress = HelperData->MaxWSAddressLength;
208  Socket->SharedData->SizeOfRemoteAddress = HelperData->MaxWSAddressLength;
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");
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,
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  }
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  }
294  }
295 
296  if (SocketType == SOCK_RAW) AfdPacket->EndpointFlags |= AFD_ENDPOINT_RAW;
297 
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  }
310 
312  {
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 
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 */
338  &DevName,
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,
349  &Object,
350  &IOSB,
351  NULL,
352  0,
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);
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,
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,
388  NULL,
389  &Socket->SharedData->SizeOfSendBuffer,
390  NULL,
391  NULL,
392  NULL);
393 
394  GetSocketInformation (Socket,
396  NULL,
397  &Socket->SharedData->SizeOfRecvBuffer,
398  NULL,
399  NULL,
400  NULL);
401 ok:
402 
403  /* Save in Process Sockets List */
405  Socket->NextSocket = SocketListHead;
406  SocketListHead = Socket;
408 
409  /* Create the Socket Context */
410  CreateContext(Socket);
411 
412  /* Notify Winsock */
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
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)
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)) )
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  {
476  NULL,
478  0,
479  (sizeof(SOCK_SHARED_INFO) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1),
480  NULL);
481  if( Socket->SharedDataHandle == INVALID_HANDLE_VALUE )
483  pSharedData = MapViewOfFile(Socket->SharedDataHandle,
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,
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,
514  NtClose(hProcess);
515  if( !bDuplicated )
516  return MsafdReturnWithErrno(STATUS_ACCESS_DENIED, lpErrno, 0, NULL);
517 
518 
519  if (!lpProtocolInfo)
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
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 
561  return WSAEMSGSIZE;
562 
563  case STATUS_NO_MEMORY:
565  return WSAENOBUFS;
566 
568  return WSAENOTCONN;
569 
571  return WSAEAFNOSUPPORT;
572 
574  return WSAEADDRNOTAVAIL;
575 
578  return WSAECONNREFUSED;
579 
581  return WSAENETUNREACH;
582 
584  return WSAEHOSTUNREACH;
585 
587  return WSAEINVAL;
588 
589  case STATUS_CANCELLED:
590  return WSA_OPERATION_ABORTED;
591 
593  return WSAEADDRINUSE;
594 
596  return WSAECONNABORTED;
597 
599  return WSAEFAULT;
600 
602  return WSAEACCES;
603 
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
624  OUT LPINT lpErrno)
625 {
627  PSOCKET_INFORMATION Socket = NULL, CurrentSocket;
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 */
646  NULL,
648  FALSE);
649 
650  if(!NT_SUCCESS(Status))
651  {
652  ERR("NtCreateEvent failed: 0x%08x", Status);
653  return SOCKET_ERROR;
654  }
655 
656  if (Socket->HelperEvents & WSH_NOTIFY_CLOSE)
657  {
658  Status = Socket->HelperData->WSHNotify(Socket->HelperContext,
659  Socket->Handle,
660  Socket->TdiAddressHandle,
661  Socket->TdiConnectionHandle,
663 
664  if (Status)
665  {
666  if (lpErrno) *lpErrno = Status;
667  ERR("WSHNotify failed. Error 0x%#x", Status);
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");
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,
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");
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 */
765  SockEvent,
766  NULL,
767  NULL,
768  &IoStatusBlock,
770  &DisconnectInfo,
771  sizeof(DisconnectInfo),
772  NULL,
773  0);
774 
775  /* Wait for return */
776  if (Status == STATUS_PENDING)
777  {
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:
794  if (SocketListHead == Socket)
795  {
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  }
813 
814  /* Close the handle */
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
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;
855  SOCKADDR_INFO SocketInfo;
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 
889  NULL,
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  {
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 */
933  SockEvent,
934  NULL,
935  NULL,
936  &IOSB,
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  {
947  Status = IOSB.Status;
948  }
949 
950  NtClose( SockEvent );
951  HeapFree(GlobalHeap, 0, BindData);
952 
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,
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
982  int Backlog,
983  LPINT lpErrno)
984 {
985  IO_STATUS_BLOCK IOSB;
986  AFD_LISTEN_DATA ListenData;
987  PSOCKET_INFORMATION Socket = NULL;
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 
1004  NULL,
1006  FALSE);
1007 
1008  if( !NT_SUCCESS(Status) )
1009  return SOCKET_ERROR;
1010 
1011  /* Set Up Listen Structure */
1012  ListenData.UseSAN = FALSE;
1014  ListenData.Backlog = Backlog;
1015 
1016  /* Send IOCTL */
1018  SockEvent,
1019  NULL,
1020  NULL,
1021  &IOSB,
1023  &ListenData,
1024  sizeof(ListenData),
1025  NULL,
1026  0);
1027 
1028  /* Wait for return */
1029  if (Status == STATUS_PENDING)
1030  {
1032  Status = IOSB.Status;
1033  }
1034 
1035  NtClose( SockEvent );
1036 
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,
1051 
1052  if (Status)
1053  {
1054  if (lpErrno) *lpErrno = Status;
1055  return SOCKET_ERROR;
1056  }
1057  }
1058 
1059  return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL );
1060 }
1061 
1062 
1063 int
1064 WSPAPI
1065 WSPSelect(IN int nfds,
1066  IN OUT fd_set *readfds OPTIONAL,
1067  IN OUT fd_set *writefds OPTIONAL,
1068  IN OUT fd_set *exceptfds OPTIONAL,
1069  IN const struct timeval *timeout OPTIONAL,
1070  OUT LPINT lpErrno)
1071 {
1072  IO_STATUS_BLOCK IOSB;
1073  PAFD_POLL_INFO PollInfo;
1074  NTSTATUS Status;
1075  ULONG HandleCount;
1076  ULONG PollBufferSize;
1077  PVOID PollBuffer;
1078  ULONG i, j = 0, x;
1079  HANDLE SockEvent;
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  {
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 
1151  NULL,
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 |
1214  AFD_EVENT_ABORT |
1215  AFD_EVENT_CLOSE |
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 */
1292  SockEvent,
1293  NULL,
1294  NULL,
1295  &IOSB,
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  {
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)
1350  if ((Events & x) == AFD_EVENT_ABORT)
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;
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
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 
1427  SystemTimeToFileTime(&st1970, &u1970.ft);
1428  return (DWORD)((Time.ll - u1970.ll) / 10000000ULL);
1429 }
1430 
1432 SOCKET
1433 WSPAPI
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;
1456  GROUP GroupID = 0;
1457  ULONG CallBack;
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 
1485  NULL,
1487  FALSE);
1488 
1489  if( !NT_SUCCESS(Status) )
1490  {
1491  return SOCKET_ERROR;
1492  }
1493 
1494  /* Dynamic Structure...ugh */
1495  ListenReceiveData = (PAFD_RECEIVED_ACCEPT_DATA)ReceiveBuffer;
1496 
1497  /* If this is non-blocking, make sure there's something for us to accept */
1498  FD_ZERO(&ReadSet);
1499  FD_SET(Socket->Handle, &ReadSet);
1500  Timeout.tv_sec=0;
1501  Timeout.tv_usec=0;
1502 
1503  if (WSPSelect(0, &ReadSet, NULL, NULL, &Timeout, lpErrno) == SOCKET_ERROR)
1504  {
1505  NtClose(SockEvent);
1506  return SOCKET_ERROR;
1507  }
1508 
1509  if (ReadSet.fd_array[0] != Socket->Handle)
1510  {
1511  NtClose(SockEvent);
1512  if (lpErrno) *lpErrno = WSAEWOULDBLOCK;
1513  return SOCKET_ERROR;
1514  }
1515 
1516  /* Send IOCTL */
1518  SockEvent,
1519  NULL,
1520  NULL,
1521  &IOSB,
1523  NULL,
1524  0,
1525  ListenReceiveData,
1526  0xA + sizeof(*ListenReceiveData));
1527 
1528  /* Wait for return */
1529  if (Status == STATUS_PENDING)
1530  {
1532  Status = IOSB.Status;
1533  }
1534 
1535  if (!NT_SUCCESS(Status))
1536  {
1537  NtClose( SockEvent );
1538  return MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
1539  }
1540 
1541  if (lpfnCondition != NULL)
1542  {
1543  if ((Socket->SharedData->ServiceFlags1 & XP1_CONNECT_DATA) != 0)
1544  {
1545  /* Find out how much data is pending */
1546  PendingAcceptData.SequenceNumber = ListenReceiveData->SequenceNumber;
1547  PendingAcceptData.ReturnSize = TRUE;
1548 
1549  /* Send IOCTL */
1551  SockEvent,
1552  NULL,
1553  NULL,
1554  &IOSB,
1556  &PendingAcceptData,
1557  sizeof(PendingAcceptData),
1558  &PendingAcceptData,
1559  sizeof(PendingAcceptData));
1560 
1561  /* Wait for return */
1562  if (Status == STATUS_PENDING)
1563  {
1565  Status = IOSB.Status;
1566  }
1567 
1568  if (!NT_SUCCESS(Status))
1569  {
1570  NtClose( SockEvent );
1571  return MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
1572  }
1573 
1574  /* How much data to allocate */
1575  PendingDataLength = IOSB.Information;
1576 
1577  if (PendingDataLength)
1578  {
1579  /* Allocate needed space */
1580  PendingData = HeapAlloc(GlobalHeap, 0, PendingDataLength);
1581  if (!PendingData)
1582  {
1584  }
1585 
1586  /* We want the data now */
1587  PendingAcceptData.ReturnSize = FALSE;
1588 
1589  /* Send IOCTL */
1591  SockEvent,
1592  NULL,
1593  NULL,
1594  &IOSB,
1596  &PendingAcceptData,
1597  sizeof(PendingAcceptData),
1598  PendingData,
1599  PendingDataLength);
1600 
1601  /* Wait for return */
1602  if (Status == STATUS_PENDING)
1603  {
1605  Status = IOSB.Status;
1606  }
1607 
1608  if (!NT_SUCCESS(Status))
1609  {
1610  NtClose( SockEvent );
1611  return MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
1612  }
1613  }
1614  }
1615 
1616  if ((Socket->SharedData->ServiceFlags1 & XP1_QOS_SUPPORTED) != 0)
1617  {
1618  /* I don't support this yet */
1619  }
1620 
1621  /* Build Callee ID */
1622  CalleeID.buf = (PVOID)Socket->LocalAddress;
1623  CalleeID.len = Socket->SharedData->SizeOfLocalAddress;
1624 
1626  if (!RemoteAddress)
1627  {
1629  }
1630 
1631  /* Set up Address in SOCKADDR Format */
1633  &ListenReceiveData->Address.Address[0].AddressType,
1634  sizeof(*RemoteAddress));
1635 
1636  /* Build Caller ID */
1637  CallerID.buf = (PVOID)RemoteAddress;
1638  CallerID.len = sizeof(*RemoteAddress);
1639 
1640  /* Build Caller Data */
1641  CallerData.buf = PendingData;
1642  CallerData.len = PendingDataLength;
1643 
1644  /* Check if socket supports Conditional Accept */
1645  if (Socket->SharedData->UseDelayedAcceptance != 0)
1646  {
1647  /* Allocate Buffer for Callee Data */
1648  CalleeDataBuffer = HeapAlloc(GlobalHeap, 0, 4096);
1649  if (!CalleeDataBuffer) {
1651  }
1652  CalleeData.buf = CalleeDataBuffer;
1653  CalleeData.len = 4096;
1654  }
1655  else
1656  {
1657  /* Nothing */
1658  CalleeData.buf = 0;
1659  CalleeData.len = 0;
1660  }
1661 
1662  /* Call the Condition Function */
1663  CallBack = (lpfnCondition)(&CallerID,
1664  CallerData.buf == NULL ? NULL : &CallerData,
1665  NULL,
1666  NULL,
1667  &CalleeID,
1668  CalleeData.buf == NULL ? NULL : &CalleeData,
1669  &GroupID,
1670  dwCallbackData);
1671 
1672  if (((CallBack == CF_ACCEPT) && GroupID) != 0)
1673  {
1674  /* TBD: Check for Validity */
1675  }
1676 
1677  if (CallBack == CF_ACCEPT)
1678  {
1679  if ((Socket->SharedData->ServiceFlags1 & XP1_QOS_SUPPORTED) != 0)
1680  {
1681  /* I don't support this yet */
1682  }
1683  if (CalleeData.buf)
1684  {
1685  // SockSetConnectData Sockets(SocketID), IOCTL_AFD_SET_CONNECT_DATA, CalleeData.Buffer, CalleeData.BuffSize, 0
1686  }
1687  }
1688  else
1689  {
1690  /* Callback rejected. Build Defer Structure */
1691  DeferData.SequenceNumber = ListenReceiveData->SequenceNumber;
1692  DeferData.RejectConnection = (CallBack == CF_REJECT);
1693 
1694  /* Send IOCTL */
1696  SockEvent,
1697  NULL,
1698  NULL,
1699  &IOSB,
1701  &DeferData,
1702  sizeof(DeferData),
1703  NULL,
1704  0);
1705 
1706  /* Wait for return */
1707  if (Status == STATUS_PENDING)
1708  {
1710  Status = IOSB.Status;
1711  }
1712 
1713  NtClose( SockEvent );
1714 
1715  if (!NT_SUCCESS(Status))
1716  {
1717  return MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
1718  }
1719 
1720  if (CallBack == CF_REJECT )
1721  {
1722  if (lpErrno) *lpErrno = WSAECONNREFUSED;
1723  return SOCKET_ERROR;
1724  }
1725  else
1726  {
1727  if (lpErrno) *lpErrno = WSAECONNREFUSED;
1728  return SOCKET_ERROR;
1729  }
1730  }
1731  }
1732 
1733  /* Create a new Socket */
1735  Socket->SharedData->SocketType,
1736  Socket->SharedData->Protocol,
1737  &Socket->ProtocolInfo,
1738  GroupID,
1739  Socket->SharedData->CreateFlags,
1740  lpErrno);
1742  return SOCKET_ERROR;
1743 
1744  /* Set up the Accept Structure */
1745  AcceptData.ListenHandle = (HANDLE)AcceptSocket;
1746  AcceptData.SequenceNumber = ListenReceiveData->SequenceNumber;
1747 
1748  /* Send IOCTL to Accept */
1750  SockEvent,
1751  NULL,
1752  NULL,
1753  &IOSB,
1755  &AcceptData,
1756  sizeof(AcceptData),
1757  NULL,
1758  0);
1759 
1760  /* Wait for return */
1761  if (Status == STATUS_PENDING)
1762  {
1764  Status = IOSB.Status;
1765  }
1766 
1768  if (!NT_SUCCESS(Status))
1769  {
1770  NtClose(SockEvent);
1771  WSPCloseSocket( AcceptSocket, lpErrno );
1772  return MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
1773  }
1774 
1775  AcceptSocketInfo = GetSocketStructure(AcceptSocket);
1776  if (!AcceptSocketInfo)
1777  {
1778  NtClose(SockEvent);
1779  WSPCloseSocket( AcceptSocket, lpErrno );
1781  }
1782 
1783  AcceptSocketInfo->SharedData->State = SocketConnected;
1784  AcceptSocketInfo->SharedData->ConnectTime = GetCurrentTimeInSeconds();
1785 
1786  /* Return Address in SOCKADDR FORMAT */
1787  if( SocketAddress )
1788  {
1789  RtlCopyMemory (SocketAddress,
1790  &ListenReceiveData->Address.Address[0].AddressType,
1791  sizeof(*RemoteAddress));
1792  if( SocketAddressLength )
1793  *SocketAddressLength = sizeof(*RemoteAddress);
1794  }
1795 
1796  NtClose( SockEvent );
1797 
1798  /* Re-enable Async Event */
1800 
1801  TRACE("Socket %x\n", AcceptSocket);
1802 
1803  if (Status == STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_ACCEPT))
1804  {
1805  Status = Socket->HelperData->WSHNotify(Socket->HelperContext,
1806  Socket->Handle,
1807  Socket->TdiAddressHandle,
1808  Socket->TdiConnectionHandle,
1810 
1811  if (Status)
1812  {
1813  if (lpErrno) *lpErrno = Status;
1814  return SOCKET_ERROR;
1815  }
1816  }
1817 
1818  if (lpErrno) *lpErrno = NO_ERROR;
1819 
1820  /* Return Socket */
1821  return AcceptSocket;
1822 }
1823 
1824 int
1825 WSPAPI
1827  const struct sockaddr * SocketAddress,
1828  int SocketAddressLength,
1829  LPWSABUF lpCallerData,
1830  LPWSABUF lpCalleeData,
1831  LPQOS lpSQOS,
1832  LPQOS lpGQOS,
1833  LPINT lpErrno)
1834 {
1835  IO_STATUS_BLOCK IOSB;
1836  PAFD_CONNECT_INFO ConnectInfo = NULL;
1837  PSOCKET_INFORMATION Socket;
1838  NTSTATUS Status;
1839  INT Errno;
1840  ULONG ConnectDataLength;
1841  ULONG InConnectDataLength;
1842  INT BindAddressLength;
1843  PSOCKADDR BindAddress;
1844  HANDLE SockEvent;
1845  int SocketDataLength;
1846 
1847  TRACE("Called (%lx) %lx:%d\n", Handle, ((const struct sockaddr_in *)SocketAddress)->sin_addr, ((const struct sockaddr_in *)SocketAddress)->sin_port);
1848 
1849  /* Get the Socket Structure associate to this Socket*/
1850  Socket = GetSocketStructure(Handle);
1851  if (!Socket)
1852  {
1853  if (lpErrno) *lpErrno = WSAENOTSOCK;
1854  return SOCKET_ERROR;
1855  }
1856 
1859  NULL,
1861  FALSE);
1862 
1863  if (!NT_SUCCESS(Status))
1864  return SOCKET_ERROR;
1865 
1866  /* Bind us First */
1867  if (Socket->SharedData->State == SocketOpen)
1868  {
1869  /* Get the Wildcard Address */
1870  BindAddressLength = Socket->HelperData->MaxWSAddressLength;
1871  BindAddress = HeapAlloc(GetProcessHeap(), 0, BindAddressLength);
1872  if (!BindAddress)
1873  {
1874  NtClose(SockEvent);
1876  }
1878  BindAddress,
1879  &BindAddressLength);
1880  /* Bind it */
1881  if (WSPBind(Handle, BindAddress, BindAddressLength, lpErrno) == SOCKET_ERROR)
1882  return SOCKET_ERROR;
1883  }
1884 
1885  /* Set the Connect Data */
1886  if (lpCallerData != NULL)
1887  {
1888  ConnectDataLength = lpCallerData->len;
1890  SockEvent,
1891  NULL,
1892  NULL,
1893  &IOSB,
1895  lpCallerData->buf,
1896  ConnectDataLength,
1897  NULL,
1898  0);
1899  /* Wait for return */
1900  if (Status == STATUS_PENDING)
1901  {
1903  Status = IOSB.Status;
1904  }
1905 
1906  if (Status != STATUS_SUCCESS)
1907  goto notify;
1908  }
1909 
1910  /* Calculate the size of SocketAddress->sa_data */
1911  SocketDataLength = SocketAddressLength - FIELD_OFFSET(struct sockaddr, sa_data);
1912 
1913  /* Allocate a connection info buffer with SocketDataLength bytes of payload */
1914  ConnectInfo = HeapAlloc(GetProcessHeap(), 0,
1916  RemoteAddress.Address[0].Address[SocketDataLength]));
1917  if (!ConnectInfo)
1918  {
1920  goto notify;
1921  }
1922 
1923  /* Set up Address in TDI Format */
1924  ConnectInfo->RemoteAddress.TAAddressCount = 1;
1925  ConnectInfo->RemoteAddress.Address[0].AddressLength = SocketDataLength;
1926  ConnectInfo->RemoteAddress.Address[0].AddressType = SocketAddress->sa_family;
1927  RtlCopyMemory(ConnectInfo->RemoteAddress.Address[0].Address,
1928  SocketAddress->sa_data,
1929  SocketDataLength);
1930 
1931  /*
1932  * Disable FD_WRITE and FD_CONNECT
1933  * The latter fixes a race condition where the FD_CONNECT is re-enabled
1934  * at the end of this function right after the Async Thread disables it.
1935  * This should only happen at the *next* WSPConnect
1936  */
1937  if (Socket->SharedData->AsyncEvents & FD_CONNECT)
1938  {
1940  }
1941 
1942  /* Tell AFD that we want Connection Data back, have it allocate a buffer */
1943  if (lpCalleeData != NULL)
1944  {
1945  InConnectDataLength = lpCalleeData->len;
1947  SockEvent,
1948  NULL,
1949  NULL,
1950  &IOSB,
1952  &InConnectDataLength,
1953  sizeof(InConnectDataLength),
1954  NULL,
1955  0);
1956 
1957  /* Wait for return */
1958  if (Status == STATUS_PENDING)
1959  {
1961  Status = IOSB.Status;
1962  }
1963 
1964  if (Status != STATUS_SUCCESS)
1965  goto notify;
1966  }
1967 
1968  /* AFD doesn't seem to care if these are invalid, but let's 0 them anyways */
1969  ConnectInfo->Root = 0;
1970  ConnectInfo->UseSAN = FALSE;
1971  ConnectInfo->Unknown = 0;
1972 
1973  /* FIXME: Handle Async Connect */
1974  if (Socket->SharedData->NonBlocking)
1975  {
1976  ERR("Async Connect UNIMPLEMENTED!\n");
1977  }
1978 
1979  /* Send IOCTL */
1981  SockEvent,
1982  NULL,
1983  NULL,
1984  &IOSB,
1986  ConnectInfo,
1987  0x22,
1988  NULL,
1989  0);
1990  /* Wait for return */
1991  if (Status == STATUS_PENDING)
1992  {
1994  Status = IOSB.Status;
1995  }
1996 
1998  if (Status != STATUS_SUCCESS)
1999  goto notify;
2000 
2001  Socket->SharedData->State = SocketConnected;
2002  Socket->TdiConnectionHandle = (HANDLE)IOSB.Information;
2004 
2005  /* Get any pending connect data */
2006  if (lpCalleeData != NULL)
2007  {
2009  SockEvent,
2010  NULL,
2011  NULL,
2012  &IOSB,
2014  NULL,
2015  0,
2016  lpCalleeData->buf,
2017  lpCalleeData->len);
2018  /* Wait for return */
2019  if (Status == STATUS_PENDING)
2020  {
2022  Status = IOSB.Status;
2023  }
2024  }
2025 
2026  TRACE("Ending %lx\n", IOSB.Status);
2027 
2028 notify:
2029  if (ConnectInfo) HeapFree(GetProcessHeap(), 0, ConnectInfo);
2030 
2031  /* Re-enable Async Event */
2033 
2034  /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */
2036 
2037  NtClose(SockEvent);
2038 
2039  if (Status == STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_CONNECT))
2040  {
2041  Errno = Socket->HelperData->WSHNotify(Socket->HelperContext,
2042  Socket->Handle,
2043  Socket->TdiAddressHandle,
2044  Socket->TdiConnectionHandle,
2046 
2047  if (Errno)
2048  {
2049  if (lpErrno) *lpErrno = Errno;
2050  return SOCKET_ERROR;
2051  }
2052  }
2053  else if (Status != STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_CONNECT_ERROR))
2054  {
2055  Errno = Socket->HelperData->WSHNotify(Socket->HelperContext,
2056  Socket->Handle,
2057  Socket->TdiAddressHandle,
2058  Socket->TdiConnectionHandle,
2060 
2061  if (Errno)
2062  {
2063  if (lpErrno) *lpErrno = Errno;
2064  return SOCKET_ERROR;
2065  }
2066  }
2067 
2068  return MsafdReturnWithErrno(Status, lpErrno, 0, NULL);
2069 }
2070 int
2071 WSPAPI
2073  int HowTo,
2074  LPINT lpErrno)
2075 
2076 {
2077  IO_STATUS_BLOCK IOSB;
2078  AFD_DISCONNECT_INFO DisconnectInfo;
2079  PSOCKET_INFORMATION Socket = NULL;
2080  NTSTATUS Status;
2081  HANDLE SockEvent;
2082 
2083  TRACE("Called\n");
2084 
2085  /* Get the Socket Structure associate to this Socket*/
2086  Socket = GetSocketStructure(Handle);
2087  if (!Socket)
2088  {
2089  if (lpErrno) *lpErrno = WSAENOTSOCK;
2090  return SOCKET_ERROR;
2091  }
2092 
2095  NULL,
2097  FALSE);
2098 
2099  if( !NT_SUCCESS(Status) )
2100  return SOCKET_ERROR;
2101 
2102  /* Set AFD Disconnect Type */
2103  switch (HowTo)
2104  {
2105  case SD_RECEIVE:
2106  DisconnectInfo.DisconnectType = AFD_DISCONNECT_RECV;
2107  Socket->SharedData->ReceiveShutdown = TRUE;
2108  break;
2109  case SD_SEND:
2110  DisconnectInfo.DisconnectType= AFD_DISCONNECT_SEND;
2111  Socket->SharedData->SendShutdown = TRUE;
2112  break;
2113  case SD_BOTH:
2115  Socket->SharedData->ReceiveShutdown = TRUE;
2116  Socket->SharedData->SendShutdown = TRUE;
2117  break;
2118  }
2119 
2120  DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(-1000000);
2121 
2122  /* Send IOCTL */
2124  SockEvent,
2125  NULL,
2126  NULL,
2127  &IOSB,
2129  &DisconnectInfo,
2130  sizeof(DisconnectInfo),
2131  NULL,
2132  0);
2133 
2134  /* Wait for return */
2135  if (Status == STATUS_PENDING)
2136  {
2138  Status = IOSB.Status;
2139  }
2140 
2141  TRACE("Ending\n");
2142 
2143  NtClose( SockEvent );
2144 
2146  return MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
2147 }
2148 
2149 
2150 INT
2151 WSPAPI
2154  IN OUT LPINT NameLength,
2155  OUT LPINT lpErrno)
2156 {
2157  IO_STATUS_BLOCK IOSB;
2158  ULONG TdiAddressSize;
2159  PTDI_ADDRESS_INFO TdiAddress;
2160  PTRANSPORT_ADDRESS SocketAddress;
2161  PSOCKET_INFORMATION Socket = NULL;
2162  NTSTATUS Status;
2163  HANDLE SockEvent;
2164 
2165  /* Get the Socket Structure associate to this Socket*/
2166  Socket = GetSocketStructure(Handle);
2167  if (!Socket)
2168  {
2169  if (lpErrno) *lpErrno = WSAENOTSOCK;
2170  return SOCKET_ERROR;
2171  }
2172 
2173  if (!Name || !NameLength)
2174  {
2175  if (lpErrno) *lpErrno = WSAEFAULT;
2176  return SOCKET_ERROR;
2177  }
2178 
2181  NULL,
2183  FALSE);
2184 
2185  if( !NT_SUCCESS(Status) )
2186  return SOCKET_ERROR;
2187 
2188  /* Allocate a buffer for the address */
2189  TdiAddressSize =
2190  sizeof(TRANSPORT_ADDRESS) + Socket->SharedData->SizeOfLocalAddress;
2191  TdiAddress = HeapAlloc(GlobalHeap, 0, TdiAddressSize);
2192 
2193  if ( TdiAddress == NULL )
2194  {
2195  NtClose( SockEvent );
2196  if (lpErrno) *lpErrno = WSAENOBUFS;
2197  return SOCKET_ERROR;
2198  }
2199 
2200  SocketAddress = &TdiAddress->Address;
2201 
2202  /* Send IOCTL */
2204  SockEvent,
2205  NULL,
2206  NULL,
2207  &IOSB,
2209  NULL,
2210  0,
2211  TdiAddress,
2212  TdiAddressSize);
2213 
2214  /* Wait for return */
2215  if (Status == STATUS_PENDING)
2216  {
2218  Status = IOSB.Status;
2219  }
2220 
2221  NtClose( SockEvent );
2222 
2223  if (NT_SUCCESS(Status))
2224  {
2225  if (*NameLength >= Socket->SharedData->SizeOfLocalAddress)
2226  {
2227  Name->sa_family = SocketAddress->Address[0].AddressType;
2228  RtlCopyMemory (Name->sa_data,
2229  SocketAddress->Address[0].Address,
2230  SocketAddress->Address[0].AddressLength);
2231  *NameLength = Socket->SharedData->SizeOfLocalAddress;
2232  TRACE("NameLength %d Address: %x Port %x\n",
2233  *NameLength, ((struct sockaddr_in *)Name)->sin_addr.s_addr,
2234  ((struct sockaddr_in *)Name)->sin_port);
2235  HeapFree(GlobalHeap, 0, TdiAddress);
2236  return 0;
2237  }
2238  else
2239  {
2240  HeapFree(GlobalHeap, 0, TdiAddress);
2241  if (lpErrno) *lpErrno = WSAEFAULT;
2242  return SOCKET_ERROR;
2243  }
2244  }
2245 
2246  HeapFree(GlobalHeap, 0, TdiAddress);
2247 
2248  return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL );
2249 }
2250 
2251 
2252 INT
2253 WSPAPI
2256  IN OUT LPINT NameLength,
2257  OUT LPINT lpErrno)
2258 {
2259  IO_STATUS_BLOCK IOSB;
2260  ULONG TdiAddressSize;
2261  PTRANSPORT_ADDRESS SocketAddress;
2262  PSOCKET_INFORMATION Socket = NULL;
2263  NTSTATUS Status;
2264  HANDLE SockEvent;
2265 
2266  /* Get the Socket Structure associate to this Socket*/
2267  Socket = GetSocketStructure(s);
2268  if (!Socket)
2269  {
2270  if (lpErrno) *lpErrno = WSAENOTSOCK;
2271  return SOCKET_ERROR;
2272  }
2273 
2274  if (Socket->SharedData->State != SocketConnected)
2275  {
2276  if (lpErrno) *lpErrno = WSAENOTCONN;
2277  return SOCKET_ERROR;
2278  }
2279 
2280  if (!Name || !NameLength)
2281  {
2282  if (lpErrno) *lpErrno = WSAEFAULT;
2283  return SOCKET_ERROR;
2284  }
2285 
2288  NULL,
2290  FALSE);
2291 
2292  if( !NT_SUCCESS(Status) )
2293  return SOCKET_ERROR;
2294 
2295  /* Allocate a buffer for the address */
2296  TdiAddressSize = sizeof(TRANSPORT_ADDRESS) + Socket->SharedData->SizeOfRemoteAddress;
2297  SocketAddress = HeapAlloc(GlobalHeap, 0, TdiAddressSize);
2298 
2299  if ( SocketAddress == NULL )
2300  {
2301  NtClose( SockEvent );
2302  if (lpErrno) *lpErrno = WSAENOBUFS;
2303  return SOCKET_ERROR;
2304  }
2305 
2306  /* Send IOCTL */
2308  SockEvent,
2309  NULL,
2310  NULL,
2311  &IOSB,
2313  NULL,
2314  0,
2315  SocketAddress,
2316  TdiAddressSize);
2317 
2318  /* Wait for return */
2319  if (Status == STATUS_PENDING)
2320  {
2322  Status = IOSB.Status;
2323  }
2324 
2325  NtClose( SockEvent );
2326 
2327  if (NT_SUCCESS(Status))
2328  {
2329  if (*NameLength >= Socket->SharedData->SizeOfRemoteAddress)
2330  {
2331  Name->sa_family = SocketAddress->Address[0].AddressType;
2332  RtlCopyMemory (Name->sa_data,
2333  SocketAddress->Address[0].Address,
2334  SocketAddress->Address[0].AddressLength);
2335  *NameLength = Socket->SharedData->SizeOfRemoteAddress;
2336  TRACE("NameLength %d Address: %x Port %x\n",
2337  *NameLength, ((struct sockaddr_in *)Name)->sin_addr.s_addr,
2338  ((struct sockaddr_in *)Name)->sin_port);
2339  HeapFree(GlobalHeap, 0, SocketAddress);
2340  return 0;
2341  }
2342  else
2343  {
2344  HeapFree(GlobalHeap, 0, SocketAddress);
2345  if (lpErrno) *lpErrno = WSAEFAULT;
2346  return SOCKET_ERROR;
2347  }
2348  }
2349 
2350  HeapFree(GlobalHeap, 0, SocketAddress);
2351 
2352  return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL );
2353 }
2354 
2355 INT
2356 WSPAPI
2359  IN LPVOID lpvInBuffer,
2360  IN DWORD cbInBuffer,
2361  OUT LPVOID lpvOutBuffer,
2362  IN DWORD cbOutBuffer,
2363  OUT LPDWORD lpcbBytesReturned,
2365  IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
2366  IN LPWSATHREADID lpThreadId,
2367  OUT LPINT lpErrno)
2368 {
2369  PSOCKET_INFORMATION Socket = NULL;
2370  BOOL NeedsCompletion = lpOverlapped != NULL;
2371  BOOLEAN NonBlocking;
2372  INT Errno = NO_ERROR, Ret = SOCKET_ERROR;
2373  DWORD cbRet = 0;
2374 
2375  /* Get the Socket Structure associate to this Socket*/
2376  Socket = GetSocketStructure(Handle);
2377  if (!Socket)
2378  {
2379  if(lpErrno)
2380  *lpErrno = WSAENOTSOCK;
2381  return SOCKET_ERROR;
2382  }
2383 
2384  if (!lpcbBytesReturned && !lpOverlapped)
2385  {
2386  if(lpErrno)
2387  *lpErrno = WSAEFAULT;
2388  return SOCKET_ERROR;
2389  }
2390 
2391  switch( dwIoControlCode )
2392  {
2393  case FIONBIO:
2394  if( cbInBuffer < sizeof(INT) || IS_INTRESOURCE(lpvInBuffer) )
2395  {
2396  Errno = WSAEFAULT;
2397  break;
2398  }
2399  NonBlocking = *((PULONG)lpvInBuffer) ? TRUE : FALSE;
2400  /* Don't allow to go in blocking mode if WSPAsyncSelect or WSPEventSelect is pending */
2401  if (!NonBlocking)
2402  {
2403  /* If there is an WSPAsyncSelect pending, fail with WSAEINVAL */
2404  if (Socket->SharedData->AsyncEvents & (~Socket->SharedData->AsyncDisabledEvents))
2405  {
2406  Errno = WSAEINVAL;
2407  break;
2408  }
2409  /* If there is an WSPEventSelect pending, fail with WSAEINVAL */
2410  if (Socket->NetworkEvents)
2411  {
2412  Errno = WSAEINVAL;
2413  break;
2414  }
2415  }
2416  Socket->SharedData->NonBlocking = NonBlocking ? 1 : 0;
2417  NeedsCompletion = FALSE;
2418  Errno = SetSocketInformation(Socket, AFD_INFO_BLOCKING_MODE, &NonBlocking, NULL, NULL, lpOverlapped, lpCompletionRoutine);
2419  if (Errno == NO_ERROR)
2420  Ret = NO_ERROR;
2421  break;
2422  case FIONREAD:
2423  if (IS_INTRESOURCE(lpvOutBuffer) || cbOutBuffer == 0)
2424  {
2425  cbRet = sizeof(ULONG);
2426  Errno = WSAEFAULT;
2427  break;
2428  }
2429  if (cbOutBuffer < sizeof(ULONG))
2430  {
2431  Errno = WSAEINVAL;
2432  break;
2433  }
2434  NeedsCompletion = FALSE;
2435  Errno = GetSocketInformation(Socket, AFD_INFO_RECEIVE_CONTENT_SIZE, NULL, (PULONG)lpvOutBuffer, NULL, lpOverlapped, lpCompletionRoutine);
2436  if (Errno == NO_ERROR)
2437  {
2438  cbRet = sizeof(ULONG);
2439  Ret = NO_ERROR;
2440  }
2441  break;
2442  case SIOCATMARK:
2443  if (IS_INTRESOURCE(lpvOutBuffer) || cbOutBuffer == 0)
2444  {
2445  cbRet = sizeof(BOOL);
2446  Errno = WSAEFAULT;
2447  break;
2448  }
2449  if (cbOutBuffer < sizeof(BOOL))
2450  {
2451  Errno = WSAEINVAL;
2452  break;
2453  }
2454  if (Socket->SharedData->SocketType != SOCK_STREAM)
2455  {
2456  Errno = WSAEINVAL;
2457  break;
2458  }
2459 
2460  /* FIXME: Return false if OOBINLINE is true for now
2461  We should MSG_PEEK|MSG_OOB check with driver
2462  */
2463  *(BOOL*)lpvOutBuffer = !Socket->SharedData->OobInline;
2464 
2465  cbRet = sizeof(BOOL);
2466  Errno = NO_ERROR;
2467  Ret = NO_ERROR;
2468  break;
2470  if (cbOutBuffer == 0)
2471  {
2472  cbRet = sizeof(PVOID);
2473  Errno = WSAEFAULT;
2474  break;
2475  }
2476 
2477  if (cbInBuffer < sizeof(GUID) ||
2478  cbOutBuffer < sizeof(PVOID))
2479  {
2480  Errno = WSAEINVAL;
2481  break;
2482  }
2483 
2484  {
2485  GUID AcceptExGUID = WSAID_ACCEPTEX;
2486  GUID ConnectExGUID = WSAID_CONNECTEX;
2487  GUID DisconnectExGUID = WSAID_DISCONNECTEX;
2488  GUID GetAcceptExSockaddrsGUID = WSAID_GETACCEPTEXSOCKADDRS;
2489 
2490  if (IsEqualGUID(&AcceptExGUID, lpvInBuffer))
2491  {
2492  *((PVOID *)lpvOutBuffer) = WSPAcceptEx;
2493  cbRet = sizeof(PVOID);
2494  Errno = NO_ERROR;
2495  Ret = NO_ERROR;
2496  }
2497  else if (IsEqualGUID(&ConnectExGUID, lpvInBuffer))
2498  {
2499  *((PVOID *)lpvOutBuffer) = WSPConnectEx;
2500  cbRet = sizeof(PVOID);
2501  Errno = NO_ERROR;
2502  Ret = NO_ERROR;
2503  }
2504  else if (IsEqualGUID(&DisconnectExGUID, lpvInBuffer))
2505  {
2506  *((PVOID *)lpvOutBuffer) = WSPDisconnectEx;
2507  cbRet = sizeof(PVOID);
2508  Errno = NO_ERROR;
2509  Ret = NO_ERROR;
2510  }
2511  else if (IsEqualGUID(&GetAcceptExSockaddrsGUID, lpvInBuffer))
2512  {
2513  *((PVOID *)lpvOutBuffer) = WSPGetAcceptExSockaddrs;
2514  cbRet = sizeof(PVOID);
2515  Errno = NO_ERROR;
2516  Ret = NO_ERROR;
2517  }
2518  else
2519  {
2520  ERR("Querying unknown extension function: %x\n", ((GUID*)lpvInBuffer)->Data1);
2521  Errno = WSAEOPNOTSUPP;
2522  }
2523  }
2524 
2525  break;
2527  if (IS_INTRESOURCE(lpvOutBuffer) || cbOutBuffer == 0)
2528  {
2529  cbRet = sizeof(SOCKET_ADDRESS_LIST) + sizeof(Socket->SharedData->WSLocalAddress);
2530  Errno = WSAEFAULT;
2531  break;
2532  }
2533  if (cbOutBuffer < sizeof(INT))
2534  {
2535  Errno = WSAEINVAL;
2536  break;
2537  }
2538 
2539  cbRet = sizeof(SOCKET_ADDRESS_LIST) + sizeof(Socket->SharedData->WSLocalAddress);
2540 
2541  ((SOCKET_ADDRESS_LIST*)lpvOutBuffer)->iAddressCount = 1;
2542 
2543  if (cbOutBuffer < (sizeof(SOCKET_ADDRESS_LIST) + sizeof(Socket->SharedData->WSLocalAddress)))
2544  {
2545  Errno = WSAEFAULT;
2546  break;
2547  }
2548 
2549  ((SOCKET_ADDRESS_LIST*)lpvOutBuffer)->Address[0].iSockaddrLength = sizeof(Socket->SharedData->WSLocalAddress);
2550  ((SOCKET_ADDRESS_LIST*)lpvOutBuffer)->Address[0].lpSockaddr = &Socket->SharedData->WSLocalAddress;
2551 
2552  Errno = NO_ERROR;
2553  Ret = NO_ERROR;
2554  break;
2555  default:
2556  Errno = Socket->HelperData->WSHIoctl(Socket->HelperContext,
2557  Handle,
2558  Socket->TdiAddressHandle,
2559  Socket->TdiConnectionHandle,
2561  lpvInBuffer,
2562  cbInBuffer,
2563  lpvOutBuffer,
2564  cbOutBuffer,
2565  &cbRet,
2566  lpOverlapped,
2567  lpCompletionRoutine,
2568  &NeedsCompletion);
2569 
2570  if (Errno == NO_ERROR)
2571  Ret = NO_ERROR;
2572  break;
2573  }
2574  if (lpOverlapped && NeedsCompletion)
2575  {
2576  lpOverlapped->Internal = Errno;
2577  lpOverlapped->InternalHigh = cbRet;
2578  if (lpCompletionRoutine != NULL)
2579  {
2580  lpCompletionRoutine(Errno, cbRet, lpOverlapped, 0);
2581  }
2582  if (lpOverlapped->hEvent)
2583  SetEvent(lpOverlapped->hEvent);
2585  {
2586  ERR("PostQueuedCompletionStatus failed %d\n", GetLastError());
2587  }
2588  return NO_ERROR;
2589  }
2590  if (lpErrno)
2591  *lpErrno = Errno;
2592  if (lpcbBytesReturned)
2593  *lpcbBytesReturned = cbRet;
2594  return Ret;
2595 }
2596 
2597 
2598 INT
2599 WSPAPI
2601  IN INT Level,
2602  IN INT OptionName,
2603  OUT CHAR FAR* OptionValue,
2604  IN OUT LPINT OptionLength,
2605  OUT LPINT lpErrno)
2606 {
2607  PSOCKET_INFORMATION Socket = NULL;
2608  PVOID Buffer;
2609  INT BufferSize;
2610  BOOL BoolBuffer;
2611  DWORD DwordBuffer;
2612  INT Errno;
2613 
2614  TRACE("Called\n");
2615 
2616  /* Get the Socket Structure associate to this Socket*/
2617  Socket = GetSocketStructure(Handle);
2618  if (Socket == NULL)
2619  {
2620  if (lpErrno) *lpErrno = WSAENOTSOCK;
2621  return SOCKET_ERROR;
2622  }
2623  if (!OptionLength || !OptionValue)
2624  {
2625  if (lpErrno) *lpErrno = WSAEFAULT;
2626  return SOCKET_ERROR;
2627  }
2628 
2629  switch (Level)
2630  {
2631  case SOL_SOCKET:
2632  switch (OptionName)
2633  {
2634  case SO_TYPE:
2635  Buffer = &Socket->SharedData->SocketType;
2636  BufferSize = sizeof(INT);
2637  break;
2638 
2639  case SO_RCVBUF:
2640  Buffer = &Socket->SharedData->SizeOfRecvBuffer;
2641  BufferSize = sizeof(ULONG);
2642  break;
2643 
2644  case SO_SNDBUF:
2645  Buffer = &Socket->SharedData->SizeOfSendBuffer;
2646  BufferSize = sizeof(ULONG);
2647  break;
2648 
2649  case SO_ACCEPTCONN:
2650  BoolBuffer = Socket->SharedData->Listening;
2651  Buffer = &BoolBuffer;
2652  BufferSize = sizeof(BOOL);
2653  break;
2654 
2655  case SO_BROADCAST:
2656  BoolBuffer = Socket->SharedData->Broadcast;
2657  Buffer = &BoolBuffer;
2658  BufferSize = sizeof(BOOL);
2659  break;
2660 
2661  case SO_DEBUG:
2662  BoolBuffer = Socket->SharedData->Debug;
2663  Buffer = &BoolBuffer;
2664  BufferSize = sizeof(BOOL);
2665  break;
2666 
2667  case SO_DONTLINGER:
2668  BoolBuffer = (Socket->SharedData->LingerData.l_onoff == 0);
2669  Buffer = &BoolBuffer;
2670  BufferSize = sizeof(BOOL);
2671  break;
2672 
2673  case SO_LINGER:
2674  if (Socket->SharedData->SocketType == SOCK_DGRAM)
2675  {
2676  if (lpErrno) *lpErrno = WSAENOPROTOOPT;
2677  return SOCKET_ERROR;
2678  }
2679  Buffer = &Socket->SharedData->LingerData;
2680  BufferSize = sizeof(struct linger);
2681  break;
2682 
2683  case SO_OOBINLINE:
2684  BoolBuffer = (Socket->SharedData->OobInline != 0);
2685  Buffer = &BoolBuffer;
2686  BufferSize = sizeof(BOOL);
2687  break;
2688 
2689  case SO_KEEPALIVE:
2690  case SO_DONTROUTE:
2691  /* These guys go directly to the helper */
2692  goto SendToHelper;
2693 
2694  case SO_CONDITIONAL_ACCEPT:
2695  BoolBuffer = (Socket->SharedData->UseDelayedAcceptance != 0);
2696  Buffer = &BoolBuffer;
2697  BufferSize = sizeof(BOOL);
2698  break;
2699 
2700  case SO_REUSEADDR:
2701  BoolBuffer = (Socket->SharedData->ReuseAddresses != 0);
2702  Buffer = &BoolBuffer;
2703  BufferSize = sizeof(BOOL);
2704  break;
2705 
2706  case SO_EXCLUSIVEADDRUSE:
2707  BoolBuffer = (Socket->SharedData->ExclusiveAddressUse != 0);
2708  Buffer = &BoolBuffer;
2709  BufferSize = sizeof(BOOL);
2710  break;
2711 
2712  case SO_ERROR:
2713  Buffer = &Socket->SharedData->SocketLastError;
2714  BufferSize = sizeof(INT);
2715  break;
2716 
2717  case SO_CONNECT_TIME:
2718  DwordBuffer = GetCurrentTimeInSeconds() - Socket->SharedData->ConnectTime;
2719  Buffer = &DwordBuffer;
2720  BufferSize = sizeof(DWORD);
2721  break;
2722 
2723  case SO_SNDTIMEO:
2724  Buffer = &Socket->SharedData->SendTimeout;
2725  BufferSize = sizeof(DWORD);
2726  break;
2727  case SO_RCVTIMEO:
2728  Buffer = &Socket->SharedData->RecvTimeout;
2729  BufferSize = sizeof(DWORD);
2730  break;
2731  case SO_PROTOCOL_INFOW:
2732  Buffer = &Socket->ProtocolInfo;
2733  BufferSize = sizeof(Socket->ProtocolInfo);
2734  break;
2735 
2736  case SO_GROUP_ID:
2737  case SO_GROUP_PRIORITY:
2738  case SO_MAX_MSG_SIZE:
2739 
2740  default:
2741  DbgPrint("MSAFD: Get unknown optname %x\n", OptionName);
2742  if (lpErrno) *lpErrno = WSAENOPROTOOPT;
2743  return SOCKET_ERROR;
2744  }
2745 
2746  if (*OptionLength < BufferSize)
2747  {
2748  if (lpErrno) *lpErrno = WSAEFAULT;
2749  *OptionLength = BufferSize;
2750  return SOCKET_ERROR;
2751  }
2752  RtlCopyMemory(OptionValue, Buffer, BufferSize);
2753 
2754  return 0;
2755 
2756  default:
2757  if (lpErrno) *lpErrno = WSAEINVAL;
2758  return SOCKET_ERROR;
2759  }
2760 
2761 SendToHelper:
2762  Errno = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext,
2763  Handle,
2764  Socket->TdiAddressHandle,
2765  Socket->TdiConnectionHandle,
2766  Level,
2767  OptionName,
2768  OptionValue,
2769  (LPINT)OptionLength);
2770  if (lpErrno) *lpErrno = Errno;
2771  return (Errno == NO_ERROR) ? NO_ERROR : SOCKET_ERROR;
2772 }
2773 
2774 INT
2775 WSPAPI
2777  IN SOCKET s,
2778  IN INT level,
2779  IN INT optname,
2780  IN CONST CHAR FAR* optval,
2781  IN INT optlen,
2782  OUT LPINT lpErrno)
2783 {
2784  PSOCKET_INFORMATION Socket;
2785  INT Errno;
2786 
2787  /* Get the Socket Structure associate to this Socket*/
2788  Socket = GetSocketStructure(s);
2789  if (Socket == NULL)
2790  {
2791  if (lpErrno) *lpErrno = WSAENOTSOCK;
2792  return SOCKET_ERROR;
2793  }
2794  if (!optval)
2795  {
2796  if (lpErrno) *lpErrno = WSAEFAULT;
2797  return SOCKET_ERROR;
2798  }
2799 
2800 
2801  /* FIXME: We should handle some more cases here */
2802  if (level == SOL_SOCKET)
2803  {
2804  switch (optname)
2805  {
2806  case SO_BROADCAST:
2807  if (optlen < sizeof(BOOL))
2808  {
2809  if (lpErrno) *lpErrno = WSAEFAULT;
2810  return SOCKET_ERROR;
2811  }
2812  Socket->SharedData->Broadcast = (*optval != 0) ? 1 : 0;
2813  return NO_ERROR;
2814 
2815  case SO_OOBINLINE:
2816  if (optlen < sizeof(BOOL))
2817  {
2818  if (lpErrno) *lpErrno = WSAEFAULT;
2819  return SOCKET_ERROR;
2820  }
2821  Socket->SharedData->OobInline = (*optval != 0) ? 1 : 0;
2822  return NO_ERROR;
2823 
2824  case SO_DONTLINGER:
2825  if (optlen < sizeof(BOOL))
2826  {
2827  if (lpErrno) *lpErrno = WSAEFAULT;
2828  return SOCKET_ERROR;
2829  }
2830  Socket->SharedData->LingerData.l_onoff = (*optval != 0) ? 0 : 1;
2831  return NO_ERROR;
2832 
2833  case SO_REUSEADDR:
2834  if (optlen < sizeof(BOOL))
2835  {
2836  if (lpErrno) *lpErrno = WSAEFAULT;
2837  return SOCKET_ERROR;
2838  }
2839  Socket->SharedData->ReuseAddresses = (*optval != 0) ? 1 : 0;
2840  return NO_ERROR;
2841 
2842  case SO_EXCLUSIVEADDRUSE:
2843  if (optlen < sizeof(BOOL))
2844  {
2845  if (lpErrno) *lpErrno = WSAEFAULT;
2846  return SOCKET_ERROR;
2847  }
2848  Socket->SharedData->ExclusiveAddressUse = (*optval != 0) ? 1 : 0;
2849  return NO_ERROR;
2850 
2851  case SO_LINGER:
2852  if (optlen < sizeof(struct linger))
2853  {
2854  if (lpErrno) *lpErrno = WSAEFAULT;
2855  return SOCKET_ERROR;
2856  }
2858  optval,
2859  sizeof(struct linger));
2860  return NO_ERROR;
2861 
2862  case SO_SNDBUF:
2863  if (optlen < sizeof(ULONG))
2864  {
2865  if (lpErrno) *lpErrno = WSAEFAULT;
2866  return SOCKET_ERROR;
2867  }
2868 
2869  SetSocketInformation(Socket,
2871  NULL,
2872  (PULONG)optval,
2873  NULL,
2874  NULL,
2875  NULL);
2876  GetSocketInformation(Socket,
2878  NULL,
2879  &Socket->SharedData->SizeOfSendBuffer,
2880  NULL,
2881  NULL,
2882  NULL);
2883 
2884  return NO_ERROR;
2885 
2886  case SO_RCVBUF:
2887  if (optlen < sizeof(ULONG))
2888  {
2889  if (lpErrno) *lpErrno = WSAEFAULT;
2890  return SOCKET_ERROR;
2891  }
2892 
2893  SetSocketInformation(Socket,
2895  NULL,
2896  (PULONG)optval,
2897  NULL,
2898  NULL,
2899  NULL);
2900  GetSocketInformation(Socket,
2902  NULL,
2903  &Socket->SharedData->SizeOfRecvBuffer,
2904  NULL,
2905  NULL,
2906  NULL);
2907 
2908  return NO_ERROR;
2909 
2910  case SO_ERROR:
2911  if (optlen < sizeof(INT))
2912  {
2913  if (lpErrno) *lpErrno = WSAEFAULT;
2914  return SOCKET_ERROR;
2915  }
2916 
2918  optval,
2919  sizeof(INT));
2920  return NO_ERROR;
2921 
2922  case SO_SNDTIMEO:
2923  if (optlen < sizeof(DWORD))
2924  {
2925  if (lpErrno) *lpErrno = WSAEFAULT;
2926  return SOCKET_ERROR;
2927  }
2928 
2930  optval,
2931  sizeof(DWORD));
2932  return NO_ERROR;
2933 
2934  case SO_RCVTIMEO:
2935  if (optlen < sizeof(DWORD))
2936  {
2937  if (lpErrno) *lpErrno = WSAEFAULT;
2938  return SOCKET_ERROR;
2939  }
2940 
2942  optval,
2943  sizeof(DWORD));
2944  return NO_ERROR;
2945 
2946  case SO_KEEPALIVE:
2947  case SO_DONTROUTE:
2948  /* These go directly to the helper dll */
2949  goto SendToHelper;
2950 
2951  default:
2952  /* Obviously this is a hack */
2953  ERR("MSAFD: Set unknown optname %x\n", optname);
2954  return NO_ERROR;
2955  }
2956  }
2957 
2958 SendToHelper:
2959  Errno = Socket->HelperData->WSHSetSocketInformation(Socket->HelperContext,
2960  s,
2961  Socket->TdiAddressHandle,
2962  Socket->TdiConnectionHandle,
2963  level,
2964  optname,
2965  (PCHAR)optval,
2966  optlen);
2967  if (lpErrno) *lpErrno = Errno;
2968  return (Errno == NO_ERROR) ? NO_ERROR : SOCKET_ERROR;
2969 }
2970 
2971 /*
2972  * FUNCTION: Initialize service provider for a client
2973  * ARGUMENTS:
2974  * wVersionRequested = Highest WinSock SPI version that the caller can use
2975  * lpWSPData = Address of WSPDATA structure to initialize
2976  * lpProtocolInfo = Pointer to structure that defines the desired protocol
2977  * UpcallTable = Pointer to upcall table of the WinSock DLL
2978  * lpProcTable = Address of procedure table to initialize
2979  * RETURNS:
2980  * Status of operation
2981  */
2983 int
2984 WSPAPI
2986  _In_ WORD wVersionRequested,
2987  _In_ LPWSPDATA lpWSPData,
2988  _In_ LPWSAPROTOCOL_INFOW lpProtocolInfo,
2989  _In_ WSPUPCALLTABLE UpcallTable,
2990  _Out_ LPWSPPROC_TABLE lpProcTable)
2991 {
2992  NTSTATUS Status;
2993 
2994  if (((LOBYTE(wVersionRequested) == 2) && (HIBYTE(wVersionRequested) < 2)) ||
2995  (LOBYTE(wVersionRequested) < 2))
2996  {
2997  ERR("WSPStartup NOT SUPPORTED for version 0x%X\n", wVersionRequested);
2998  return WSAVERNOTSUPPORTED;
2999  }
3000  else
3001  Status = NO_ERROR;
3002  /* FIXME: Enable all cases of WSPStartup status */
3003  Upcalls = UpcallTable;
3004 
3005  if (Status == NO_ERROR)
3006  {
3007  lpProcTable->lpWSPAccept = WSPAccept;
3008  lpProcTable->lpWSPAddressToString = WSPAddressToString;
3009  lpProcTable->lpWSPAsyncSelect = WSPAsyncSelect;
3010  lpProcTable->lpWSPBind = WSPBind;
3011  lpProcTable->lpWSPCancelBlockingCall = WSPCancelBlockingCall;
3012  lpProcTable->lpWSPCleanup = WSPCleanup;
3013  lpProcTable->lpWSPCloseSocket = WSPCloseSocket;
3014  lpProcTable->lpWSPConnect = WSPConnect;
3015  lpProcTable->lpWSPDuplicateSocket = WSPDuplicateSocket;
3016  lpProcTable->lpWSPEnumNetworkEvents = WSPEnumNetworkEvents;
3017  lpProcTable->lpWSPEventSelect = WSPEventSelect;
3018  lpProcTable->lpWSPGetOverlappedResult = WSPGetOverlappedResult;
3019  lpProcTable->lpWSPGetPeerName = WSPGetPeerName;
3020  lpProcTable->lpWSPGetSockName = WSPGetSockName;
3021  lpProcTable->lpWSPGetSockOpt = WSPGetSockOpt;
3022  lpProcTable->lpWSPGetQOSByName = WSPGetQOSByName;
3023  lpProcTable->lpWSPIoctl = WSPIoctl;
3024  lpProcTable->lpWSPJoinLeaf = WSPJoinLeaf;
3025  lpProcTable->lpWSPListen = WSPListen;
3026  lpProcTable->lpWSPRecv = WSPRecv;
3027  lpProcTable->lpWSPRecvDisconnect = WSPRecvDisconnect;
3028  lpProcTable->lpWSPRecvFrom = WSPRecvFrom;
3029  lpProcTable->lpWSPSelect = WSPSelect;
3030  lpProcTable->lpWSPSend = WSPSend;
3031  lpProcTable->lpWSPSendDisconnect = WSPSendDisconnect;
3032  lpProcTable->lpWSPSendTo = WSPSendTo;
3033  lpProcTable->lpWSPSetSockOpt = WSPSetSockOpt;
3034  lpProcTable->lpWSPShutdown = WSPShutdown;
3035  lpProcTable->lpWSPSocket = WSPSocket;
3036  lpProcTable->lpWSPStringToAddress = WSPStringToAddress;
3037  lpWSPData->wVersion = MAKEWORD(2, 2);
3038  lpWSPData->wHighVersion = MAKEWORD(2, 2);
3039  /* Save CatalogEntryId for all upcalls */
3040  CatalogEntryId = lpProtocolInfo->dwCatalogEntryId;
3041  }
3042 
3043  TRACE("Status (%d).\n", Status);
3044  return Status;
3045 }
3046 
3047 
3048 INT
3049 WSPAPI
3051  IN DWORD dwAddressLength,
3052  IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
3053  OUT LPWSTR lpszAddressString,
3054  IN OUT LPDWORD lpdwAddressStringLength,
3055  OUT LPINT lpErrno)
3056 {
3057  SIZE_T size;
3058  WCHAR buffer[54]; /* 32 digits + 7':' + '[' + '%" + 5 digits + ']:' + 5 digits + '\0' */
3059  WCHAR *p;
3060 
3061  if (!lpsaAddress || !lpszAddressString || !lpdwAddressStringLength)
3062  {
3063  if (lpErrno) *lpErrno = WSAEFAULT;
3064  return SOCKET_ERROR;
3065  }
3066 
3067  switch (lpsaAddress->sa_family)
3068  {
3069  case AF_INET:
3070  if (dwAddressLength < sizeof(SOCKADDR_IN))
3071  {
3072  if (lpErrno) *lpErrno = WSAEINVAL;
3073  return SOCKET_ERROR;
3074  }
3075  swprintf(buffer,
3076  L"%u.%u.%u.%u:%u",
3077  (unsigned int)(ntohl(((SOCKADDR_IN *)lpsaAddress)->sin_addr.s_addr) >> 24 & 0xff),
3078  (unsigned int)(ntohl(((SOCKADDR_IN *)lpsaAddress)->sin_addr.s_addr) >> 16 & 0xff),
3079  (unsigned int)(ntohl(((SOCKADDR_IN *)lpsaAddress)->sin_addr.s_addr) >> 8 & 0xff),
3080  (unsigned int)(ntohl(((SOCKADDR_IN *)lpsaAddress)->sin_addr.s_addr) & 0xff),
3081  ntohs(((SOCKADDR_IN *)lpsaAddress)->sin_port));
3082 
3083  p = wcschr(buffer, L':');
3084  if (!((SOCKADDR_IN *)lpsaAddress)->sin_port)
3085  {
3086  *p = 0;
3087  }
3088  break;
3089  default:
3090  if (lpErrno) *lpErrno = WSAEINVAL;
3091  return SOCKET_ERROR;
3092  }
3093 
3094  size = wcslen(buffer) + 1;
3095 
3096  if (*lpdwAddressStringLength < size)
3097  {
3098  *lpdwAddressStringLength = size;
3099  if (lpErrno) *lpErrno = WSAEFAULT;
3100  return SOCKET_ERROR;
3101  }
3102 
3103  *lpdwAddressStringLength = size;
3104  wcscpy(lpszAddressString, buffer);
3105  return 0;
3106 }
3107 
3108 INT
3109 WSPAPI
3112  IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
3113  OUT LPSOCKADDR lpAddress,
3114  IN OUT LPINT lpAddressLength,
3115  OUT LPINT lpErrno)
3116 {
3117  int numdots = 0;
3118  USHORT port;
3119  LONG inetaddr = 0, ip_part;
3120  LPWSTR *bp = NULL;
3122 
3123  if (!lpAddressLength || !lpAddress || !AddressString)
3124  {
3125  if (lpErrno) *lpErrno = WSAEINVAL;
3126  return SOCKET_ERROR;
3127  }
3128 
3129  sockaddr = (SOCKADDR_IN *)lpAddress;
3130 
3131  /* Set right address family */
3132  if (lpProtocolInfo != NULL)
3133  {
3134  sockaddr->sin_family = lpProtocolInfo->iAddressFamily;
3135  }
3136  else
3137  {
3138  sockaddr->sin_family = AddressFamily;
3139  }
3140 
3141  /* Report size */
3142  if (AddressFamily == AF_INET)
3143  {
3144  if (*lpAddressLength < (INT)sizeof(SOCKADDR_IN))
3145  {
3146  if (lpErrno) *lpErrno = WSAEFAULT;
3147  }
3148  else
3149  {
3150  // translate ip string to ip
3151 
3152  /* Get ip number */
3153  bp = &AddressString;
3154  inetaddr = 0;
3155 
3156  while (*bp < &AddressString[wcslen(AddressString)])
3157  {
3158  ip_part = wcstol(*bp, bp, 10);
3159  /* ip part number should be in range 0-255 */
3160  if (ip_part < 0 || ip_part > 255)
3161  {
3162  if (lpErrno) *lpErrno = WSAEINVAL;
3163  return SOCKET_ERROR;
3164  }
3165  inetaddr = (inetaddr << 8) + ip_part;
3166  /* we end on string end or port separator */
3167  if ((*bp)[0] == 0 || (*bp)[0] == L':')
3168  break;
3169  /* ip parts are dot separated. verify it */
3170  if ((*bp)[0] != L'.')
3171  {
3172  if (lpErrno) *lpErrno = WSAEINVAL;
3173  return SOCKET_ERROR;
3174  }
3175  /* count the dots */
3176  numdots++;
3177  /* move over the dot to next ip part */
3178  (*bp)++;
3179  }
3180 
3181  /* check dots count */
3182  if (numdots != 3)
3183  {
3184  if (lpErrno) *lpErrno = WSAEINVAL;
3185  return SOCKET_ERROR;
3186  }
3187 
3188  /* Get port number */
3189  if ((*bp)[0] == L':')
3190  {
3191  /* move over the column to port part */
3192  (*bp)++;
3193  /* next char should be numeric */
3194  if ((*bp)[0] < L'0' || (*bp)[0] > L'9')
3195  {
3196  if (lpErrno) *lpErrno = WSAEINVAL;
3197  return SOCKET_ERROR;
3198  }
3199  port = wcstol(*bp, bp, 10);
3200  }
3201  else
3202  {
3203  port = 0;
3204  }
3205 
3206  if (lpErrno) *lpErrno = NO_ERROR;
3207  /* rest sockaddr.sin_addr.s_addr
3208  for we need to be sure it is zero when we come to while */
3209  *lpAddressLength = sizeof(*sockaddr);
3210  memset(lpAddress, 0, sizeof(*sockaddr));
3211  sockaddr->sin_family = AF_INET;
3212  sockaddr->sin_addr.s_addr = inetaddr;
3213  sockaddr->sin_port = port;
3214  }
3215  }
3216 
3217  if (lpErrno && !*lpErrno)
3218  {
3219  return 0;
3220  }
3221 
3222  return SOCKET_ERROR;
3223 }
3224 
3225 /*
3226  * FUNCTION: Cleans up service provider for a client
3227  * ARGUMENTS:
3228  * lpErrno = Address of buffer for error information
3229  * RETURNS:
3230  * 0 if successful, or SOCKET_ERROR if not
3231  */
3232 INT
3233 WSPAPI
3235 
3236 {
3237  TRACE("Leaving.\n");
3238 
3239  if (lpErrno) *lpErrno = NO_ERROR;
3240 
3241  return 0;
3242 }
3243 
3244 VOID
3245 NTAPI
3248  ULONG Reserved)
3249 {
3251 
3252  Context->lpCompletionRoutine(IoStatusBlock->Status, IoStatusBlock->Information, Context->lpOverlapped, 0);
3254 }
3255 
3256 int
3258  ULONG AfdInformationClass,
3259  PBOOLEAN Boolean OPTIONAL,
3261  PLARGE_INTEGER LargeInteger OPTIONAL,
3262  LPWSAOVERLAPPED Overlapped OPTIONAL,
3264 {
3265  PIO_STATUS_BLOCK IOSB;
3266  IO_STATUS_BLOCK DummyIOSB;
3267  AFD_INFO InfoData;
3268  NTSTATUS Status;
3269  PAFDAPCCONTEXT APCContext;
3270  PIO_APC_ROUTINE APCFunction;
3271  HANDLE Event = NULL;
3272  HANDLE SockEvent;
3273 
3276  NULL,
3278  FALSE);
3279 
3280  if( !NT_SUCCESS(Status) )
3281  return SOCKET_ERROR;
3282 
3283  /* Set Info Class */
3284  InfoData.InformationClass = AfdInformationClass;
3285 
3286  /* Verify if we should use APC */
3287  if (Overlapped == NULL)
3288  {
3289  /* Not using Overlapped structure, so use normal blocking on event */
3290  APCContext = NULL;
3291  APCFunction = NULL;
3292  Event = SockEvent;
3293  IOSB = &DummyIOSB;
3294  }
3295  else
3296  {
3297  /* Overlapped request for non overlapped opened socket */
3298  if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0)
3299  {
3300  TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
3301  NtClose( SockEvent );
3302  return 0;
3303  }
3304  if (CompletionRoutine == NULL)
3305  {
3306  /* Using Overlapped Structure, but no Completition Routine, so no need for APC */
3307  APCContext = (PAFDAPCCONTEXT)Overlapped;
3308  APCFunction = NULL;
3309  Event = Overlapped->hEvent;
3310  }
3311  else
3312  {
3313  /* Using Overlapped Structure and a Completition Routine, so use an APC */
3314  APCFunction = &AfdInfoAPC; // should be a private io completition function inside us
3315  APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT));
3316  if (!APCContext)
3317  {
3318  ERR("Not enough memory for APC Context\n");
3319  NtClose( SockEvent );
3320  return WSAEFAULT;
3321  }
3322  APCContext->lpCompletionRoutine = CompletionRoutine;
3323  APCContext->lpOverlapped = Overlapped;
3324  APCContext->lpSocket = Socket;
3325  }
3326 
3327  IOSB = (PIO_STATUS_BLOCK)&Overlapped->Internal;
3328  }
3329 
3330  IOSB->Status = STATUS_PENDING;
3331 
3332  /* Send IOCTL */
3334  Event,
3335  APCFunction,
3336  APCContext,
3337  IOSB,
3339  &InfoData,
3340  sizeof(InfoData),
3341  &InfoData,
3342  sizeof(InfoData));
3343 
3344  /* Wait for return */
3345  if (Status == STATUS_PENDING && Overlapped == NULL)
3346  {
3348  Status = IOSB->Status;
3349  }
3350 
3351  NtClose( SockEvent );
3352 
3353  TRACE("Status %x Information %d\n", Status, IOSB->Information);
3354 
3355  if (Status == STATUS_PENDING)
3356  {
3357  TRACE("Leaving (Pending)\n");
3358  return WSA_IO_PENDING;
3359  }
3360 
3361  if (Status != STATUS_SUCCESS)
3362  return SOCKET_ERROR;
3363 
3364  /* Return Information */
3365  if (Ulong != NULL)
3366  {
3367  *Ulong = InfoData.Information.Ulong;
3368  }
3369  if (LargeInteger != NULL)
3370  {
3371  *LargeInteger = InfoData.Information.LargeInteger;
3372  }
3373  if (Boolean != NULL)
3374  {
3375  *Boolean = InfoData.Information.Boolean;
3376  }
3377 
3378  return NO_ERROR;
3379 
3380 }
3381 
3382 
3383 int
3385  ULONG AfdInformationClass,
3386  PBOOLEAN Boolean OPTIONAL,
3388  PLARGE_INTEGER LargeInteger OPTIONAL,
3389  LPWSAOVERLAPPED Overlapped OPTIONAL,
3391 {
3392  PIO_STATUS_BLOCK IOSB;
3393  IO_STATUS_BLOCK DummyIOSB;
3394  AFD_INFO InfoData;
3395  NTSTATUS Status;
3396  PAFDAPCCONTEXT APCContext;
3397  PIO_APC_ROUTINE APCFunction;
3398  HANDLE Event = NULL;
3399  HANDLE SockEvent;
3400 
3403  NULL,
3405  FALSE);
3406 
3407  if( !NT_SUCCESS(Status) )
3408  return SOCKET_ERROR;
3409 
3410  /* Set Info Class */
3411  InfoData.InformationClass = AfdInformationClass;
3412 
3413  /* Set Information */
3414  if (Ulong != NULL)
3415  {
3416  InfoData.Information.Ulong = *Ulong;
3417  }
3418  if (LargeInteger != NULL)
3419  {
3420  InfoData.Information.LargeInteger = *LargeInteger;
3421  }
3422  if (Boolean != NULL)
3423  {
3424  InfoData.Information.Boolean = *Boolean;
3425  }
3426 
3427  /* Verify if we should use APC */
3428  if (Overlapped == NULL)
3429  {
3430  /* Not using Overlapped structure, so use normal blocking on event */
3431  APCContext = NULL;
3432  APCFunction = NULL;
3433  Event = SockEvent;
3434  IOSB = &DummyIOSB;
3435  }
3436  else
3437  {
3438  /* Overlapped request for non overlapped opened socket */
3439  if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0)
3440  {
3441  TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
3442  NtClose( SockEvent );
3443  return 0;
3444  }
3445  if (CompletionRoutine == NULL)
3446  {
3447  /* Using Overlapped Structure, but no Completition Routine, so no need for APC */
3448  APCContext = (PAFDAPCCONTEXT)Overlapped;
3449  APCFunction = NULL;
3450  Event = Overlapped->hEvent;
3451  }
3452  else
3453  {
3454  /* Using Overlapped Structure and a Completition Routine, so use an APC */
3455  APCFunction = &AfdInfoAPC; // should be a private io completition function inside us
3456  APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT));
3457  if (!APCContext)
3458  {
3459  ERR("Not enough memory for APC Context\n");
3460  NtClose( SockEvent );
3461  return WSAEFAULT;
3462  }
3463  APCContext->lpCompletionRoutine = CompletionRoutine;
3464  APCContext->lpOverlapped = Overlapped;
3465  APCContext->lpSocket = Socket;
3466  }
3467 
3468  IOSB = (PIO_STATUS_BLOCK)&Overlapped->Internal;
3469  }
3470 
3471  IOSB->Status = STATUS_PENDING;
3472 
3473  /* Send IOCTL */
3475  Event,
3476  APCFunction,
3477  APCContext,
3478  IOSB,
3480  &InfoData,
3481  sizeof(InfoData),
3482  NULL,
3483  0);
3484 
3485  /* Wait for return */
3486  if (Status == STATUS_PENDING && Overlapped == NULL)
3487  {
3489  Status = IOSB->Status;
3490  }
3491 
3492  NtClose( SockEvent );
3493 
3494  TRACE("Status %x Information %d\n", Status, IOSB->Information);
3495 
3496  if (Status == STATUS_PENDING)
3497  {
3498  TRACE("Leaving (Pending)\n");
3499  return WSA_IO_PENDING;
3500  }
3501 
3503 
3504 }
3505 
3508 {
3509  PSOCKET_INFORMATION CurrentSocket;
3510 
3512 
3513  CurrentSocket = SocketListHead;
3514  while (CurrentSocket)
3515  {
3516  if (CurrentSocket->Handle == Handle)
3517  {
3519  return CurrentSocket;
3520  }
3521 
3522  CurrentSocket = CurrentSocket->NextSocket;
3523  }
3524 
3526 
3527  return NULL;
3528 }
3529 
3531 {
3532  IO_STATUS_BLOCK IOSB;
3533  SOCKET_CONTEXT ContextData;
3534  NTSTATUS Status;
3535  HANDLE SockEvent;
3536 
3539  NULL,
3541  FALSE);
3542 
3543  if( !NT_SUCCESS(Status) )
3544  return SOCKET_ERROR;
3545 
3546  /* Create Context */
3547  ContextData.SharedData = *Socket->SharedData;
3548  ContextData.SizeOfHelperData = 0;
3549  RtlCopyMemory (&ContextData.LocalAddress,
3550  Socket->LocalAddress,
3551  Socket->SharedData->SizeOfLocalAddress);
3552  RtlCopyMemory (&ContextData.RemoteAddress,
3553  Socket->RemoteAddress,
3554  Socket->SharedData->SizeOfRemoteAddress);
3555 
3556  /* Send IOCTL */
3558  SockEvent,
3559  NULL,
3560  NULL,
3561  &IOSB,
3563  &ContextData,
3564  sizeof(ContextData),
3565  NULL,
3566  0);
3567 
3568  /* Wait for Completion */
3569  if (Status == STATUS_PENDING)
3570  {
3572  Status = IOSB.Status;
3573  }
3574 
3575  NtClose( SockEvent );
3576 
3578 }
3579 
3581 {
3582  HANDLE hAsyncThread;
3583  DWORD AsyncThreadId;
3584  HANDLE AsyncEvent;
3586  NTSTATUS Status;
3587 
3588  /* Check if the Thread Already Exists */
3590  {
3592  return TRUE;
3593  }
3594 
3595  /* Create the Completion Port */
3597  {
3600  NULL,
3601  2); // Allow 2 threads only
3602  if (!NT_SUCCESS(Status))
3603  {
3604  ERR("Failed to create completion port: 0x%08x\n", Status);
3605  return FALSE;
3606  }
3607  /* Protect Handle */
3608  HandleFlags.ProtectFromClose = TRUE;
3609  HandleFlags.Inherit = FALSE;
3611  ObjectHandleFlagInformation,
3612  &HandleFlags,
3613  sizeof(HandleFlags));
3614  }
3615 
3616  /* Create the Async Event */
3617  Status = NtCreateEvent(&AsyncEvent,
3619  NULL,
3621  FALSE);
3622 
3623  /* Create the Async Thread */
3624  hAsyncThread = CreateThread(NULL,
3625  0,
3627  NULL,
3628  0,
3629  &AsyncThreadId);
3630 
3631  /* Close the Handle */
3632  NtClose(hAsyncThread);
3633 
3634  /* Increase the Reference Count */
3636  return TRUE;
3637 }
3638 
3639 ULONG
3640 NTAPI
3642 {
3643  PVOID AsyncContext;
3644  PASYNC_COMPLETION_ROUTINE AsyncCompletionRoutine;
3645  IO_STATUS_BLOCK IOSB;
3646  NTSTATUS Status;
3647 
3648  /* Make the Thread Higher Priority */
3650 
3651  /* Do a KQUEUE/WorkItem Style Loop, thanks to IoCompletion Ports */
3652  do
3653  {
3655  (PVOID*)&AsyncCompletionRoutine,
3656  &AsyncContext,
3657  &IOSB,
3658  NULL);
3659  /* Call the Async Function */
3660  if (NT_SUCCESS(Status))
3661  {
3662  (*AsyncCompletionRoutine)(AsyncContext, &IOSB);
3663  }
3664  else
3665  {
3666  /* It Failed, sleep for a second */
3667  Sleep(1000);
3668  }
3669  } while ((Status != STATUS_TIMEOUT));
3670 
3671  /* The Thread has Ended */
3672  return 0;
3673 }
3674 
3676 {
3677  UNICODE_STRING AfdHelper;
3679  IO_STATUS_BLOCK IoSb;
3680  FILE_COMPLETION_INFORMATION CompletionInfo;
3682 
3683  /* First, make sure we're not already initialized */
3685  {
3686  return TRUE;
3687  }
3688 
3689  /* Set up Handle Name and Object */
3690  RtlInitUnicodeString(&AfdHelper, L"\\Device\\Afd\\AsyncSelectHlp" );
3692  &AfdHelper,
3694  NULL,
3695  NULL);
3696 
3697  /* Open the Handle to AFD */
3701  &IoSb,
3702  NULL,
3703  0,
3705  FILE_OPEN_IF,
3706  0,
3707  NULL,
3708  0);
3709 
3710  /*
3711  * Now Set up the Completion Port Information
3712  * This means that whenever a Poll is finished, the routine will be executed
3713  */
3714  CompletionInfo.Port = SockAsyncCompletionPort;
3715  CompletionInfo.Key = SockAsyncSelectCompletionRoutine;
3717  &IoSb,
3718  &CompletionInfo,
3719  sizeof(CompletionInfo),
3721 
3722 
3723  /* Protect the Handle */
3724  HandleFlags.ProtectFromClose = TRUE;
3725  HandleFlags.Inherit = FALSE;
3727  ObjectHandleFlagInformation,
3728  &HandleFlags,
3729  sizeof(HandleFlags));
3730 
3731 
3732  /* Set this variable to true so that Send/Recv/Accept will know wether to renable disabled events */
3734  return TRUE;
3735 }
3736 
3738 {
3739 
3740  PASYNC_DATA AsyncData = Context;
3741  PSOCKET_INFORMATION Socket;
3742  ULONG x;
3743 
3744  /* Get the Socket */
3745  Socket = AsyncData->ParentSocket;
3746 
3747  /* Check if the Sequence Number Changed behind our back */
3748  if (AsyncData->SequenceNumber != Socket->SharedData->SequenceNumber )
3749  {
3750  return;
3751  }
3752 
3753  /* Check we were manually called b/c of a failure */
3755  {
3756  /* FIXME: Perform Upcall */
3757  return;
3758  }
3759 
3760  for (x = 1; x; x<<=1)
3761  {
3762  switch (AsyncData->AsyncSelectInfo.Handles[0].Events & x)
3763  {
3764  case AFD_EVENT_RECEIVE:
3765  if (0 != (Socket->SharedData->AsyncEvents & FD_READ) &&
3766  0 == (Socket->SharedData->AsyncDisabledEvents & FD_READ))
3767  {
3768  /* Make the Notification */
3770  Socket->SharedData->wMsg,
3771  Socket->Handle,
3773  /* Disable this event until the next read(); */
3775  }
3776  break;
3777 
3778  case AFD_EVENT_OOB_RECEIVE:
3779  if (0 != (Socket->SharedData->AsyncEvents & FD_OOB) &&
3780  0 == (Socket->SharedData->AsyncDisabledEvents & FD_OOB))
3781  {
3782  /* Make the Notification */
3784  Socket->SharedData->wMsg,
3785  Socket->Handle,
3787  /* Disable this event until the next read(); */
3789  }
3790  break;
3791 
3792  case AFD_EVENT_SEND:
3793  if (0 != (Socket->SharedData->AsyncEvents & FD_WRITE) &&
3794  0 == (Socket->SharedData->AsyncDisabledEvents & FD_WRITE))
3795  {
3796  /* Make the Notification */
3798  Socket->SharedData->wMsg,
3799  Socket->Handle,
3801  /* Disable this event until the next write(); */
3803  }
3804  break;
3805 
3806  /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */
3807  case AFD_EVENT_CONNECT:
3809  if (0 != (Socket->SharedData->AsyncEvents & FD_CONNECT) &&
3810  0 == (Socket->SharedData->AsyncDisabledEvents & FD_CONNECT))
3811  {
3812  /* Make the Notification */
3814  Socket->SharedData->wMsg,
3815  Socket->Handle,
3817  /* Disable this event forever; */
3819  }
3820  break;
3821 
3822  case AFD_EVENT_ACCEPT:
3823  if (0 != (Socket->SharedData->AsyncEvents & FD_ACCEPT) &&
3824  0 == (Socket->SharedData->AsyncDisabledEvents & FD_ACCEPT))
3825  {
3826  /* Make the Notification */
3828  Socket->SharedData->wMsg,
3829  Socket->Handle,
3831  /* Disable this event until the next accept(); */
3833  }
3834  break;
3835 
3836  case AFD_EVENT_DISCONNECT:
3837  case AFD_EVENT_ABORT:
3838  case AFD_EVENT_CLOSE:
3839  if (0 != (Socket->SharedData->AsyncEvents & FD_CLOSE) &&
3840  0 == (Socket->SharedData->AsyncDisabledEvents & FD_CLOSE))
3841  {
3842  /* Make the Notification */
3844  Socket->SharedData->wMsg,
3845  Socket->Handle,
3847  /* Disable this event forever; */
3849  }
3850  break;
3851  /* FIXME: Support QOS */
3852  }
3853  }
3854 
3855  /* Check if there are any events left for us to check */
3856  if ((Socket->SharedData->AsyncEvents & (~Socket->SharedData->AsyncDisabledEvents)) == 0 )
3857  {
3858  return;
3859  }
3860 
3861  /* Keep Polling */
3862  SockProcessAsyncSelect(Socket, AsyncData);
3863  return;
3864 }
3865 
3867 {
3868 
3869  ULONG lNetworkEvents;
3870  NTSTATUS Status;
3871 
3872  /* Set up the Async Data Event Info */
3873  AsyncData->AsyncSelectInfo.Timeout.HighPart = 0x7FFFFFFF;
3874  AsyncData->AsyncSelectInfo.Timeout.LowPart = 0xFFFFFFFF;
3875  AsyncData->AsyncSelectInfo.HandleCount = 1;
3876  AsyncData->AsyncSelectInfo.Exclusive = TRUE;
3877  AsyncData->AsyncSelectInfo.Handles[0].Handle = Socket->Handle;
3878  AsyncData->AsyncSelectInfo.Handles[0].Events = 0;
3879 
3880  /* Remove unwanted events */
3881  lNetworkEvents = Socket->SharedData->AsyncEvents & (~Socket->SharedData->AsyncDisabledEvents);
3882 
3883  /* Set Events to wait for */
3884  if (lNetworkEvents & FD_READ)
3885  {
3887  }
3888 
3889  if (lNetworkEvents & FD_WRITE)
3890  {
3891  AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_SEND;
3892  }
3893 
3894  if (lNetworkEvents & FD_OOB)
3895  {
3897  }
3898 
3899  if (lNetworkEvents & FD_ACCEPT)
3900  {
3902  }
3903 
3904  /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */
3905  if (lNetworkEvents & FD_CONNECT)
3906  {
3908  }
3909 
3910  if (lNetworkEvents & FD_CLOSE)
3911  {
3913  }
3914 
3915  if (lNetworkEvents & FD_QOS)
3916  {
3917  AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_QOS;
3918  }
3919 
3920  if (lNetworkEvents & FD_GROUP_QOS)
3921  {
3923  }
3924 
3925  /* Send IOCTL */
3927  NULL,
3928  NULL,
3929  AsyncData,
3930  &AsyncData->IoStatusBlock,
3932  &AsyncData->AsyncSelectInfo,
3933  sizeof(AsyncData->AsyncSelectInfo),
3934  &AsyncData->AsyncSelectInfo,
3935  sizeof(AsyncData->AsyncSelectInfo));
3936 
3937  /* I/O Manager Won't call the completion routine, let's do it manually */
3938  if (NT_SUCCESS(Status))
3939  {
3940  return;
3941  }
3942  else
3943  {
3944  AsyncData->IoStatusBlock.Status = Status;
3945  SockAsyncSelectCompletionRoutine(AsyncData, &AsyncData->IoStatusBlock);
3946  }
3947 }
3948 
3950 {
3951  PASYNC_DATA AsyncData = Context;
3952  BOOL FreeContext = TRUE;
3953  PSOCKET_INFORMATION Socket;
3954 
3955  /* Get the Socket */
3956  Socket = AsyncData->ParentSocket;
3957 
3958  /* If someone closed it, stop the function */
3959  if (Socket->SharedData->State != SocketClosed)
3960  {
3961  /* Check if the Sequence Number changed by now, in which case quit */
3962  if (AsyncData->SequenceNumber == Socket->SharedData->SequenceNumber)
3963  {
3964  /* Do the actual select, if needed */
3965  if ((Socket->SharedData->AsyncEvents & (~Socket->SharedData->AsyncDisabledEvents)))
3966  {
3967  SockProcessAsyncSelect(Socket, AsyncData);
3968  FreeContext = FALSE;
3969  }
3970  }
3971  }
3972 
3973  /* Free the Context */
3974  if (FreeContext)
3975  {
3976  HeapFree(GetProcessHeap(), 0, AsyncData);
3977  }
3978 
3979  return;
3980 }
3981 
3982 VOID
3984  IN ULONG Event)
3985 {
3986  PASYNC_DATA AsyncData;
3987 
3988  /* Make sure the event is actually disabled */
3989  if (!(Socket->SharedData->AsyncDisabledEvents & Event))
3990  {
3991  return;
3992  }
3993 
3994  /* Re-enable it */
3995  Socket->SharedData->AsyncDisabledEvents &= ~Event;
3996 
3997  /* Return if no more events are being polled */
3998  if ((Socket->SharedData->AsyncEvents & (~Socket->SharedData->AsyncDisabledEvents)) == 0 )
3999  {
4000  return;
4001  }
4002 
4003  /* Wait on new events */
4004  AsyncData = HeapAlloc(GetProcessHeap(), 0, sizeof(ASYNC_DATA));
4005  if (!AsyncData) return;
4006 
4007  /* Create the Asynch Thread if Needed */
4009 
4010  /* Increase the sequence number to stop anything else */
4011  Socket->SharedData->SequenceNumber++;
4012 
4013  /* Set up the Async Data */
4014  AsyncData->ParentSocket = Socket;
4015  AsyncData->SequenceNumber = Socket->SharedData->SequenceNumber;
4016 
4017  /* Begin Async Select by using I/O Completion */
4020  AsyncData,
4021  0,
4022  0);
4023 
4024  /* All done */
4025  return;
4026 }
4027 
4028 BOOL
4029 WINAPI
4030 DllMain(HANDLE hInstDll,
4031  ULONG dwReason,
4032  PVOID Reserved)
4033 {
4034 
4035  switch (dwReason)
4036  {
4037  case DLL_PROCESS_ATTACH:
4038 
4039  TRACE("Loading MSAFD.DLL \n");
4040 
4041  /* Don't need thread attach notifications
4042  so disable them to improve performance */
4043  DisableThreadLibraryCalls(hInstDll);
4044 
4045  /* List of DLL Helpers */
4047 
4048  /* Heap to use when allocating */
4050 
4051  /* Initialize the lock that protects our socket list */
4053 
4054  TRACE("MSAFD.DLL has been loaded\n");
4055 
4056  break;
4057 
4058  case DLL_THREAD_ATTACH:
4059  break;
4060 
4061  case DLL_THREAD_DETACH:
4062  break;
4063 
4064  case DLL_PROCESS_DETACH:
4065 
4066  /* Delete the socket list lock */
4068 
4069  break;
4070  }
4071 
4072  TRACE("DllMain of msafd.dll (leaving)\n");
4073 
4074  return TRUE;
4075 }
4076 
4077 /* EOF */
#define SIO_ADDRESS_LIST_QUERY
Definition: ws2def.h:177
PWSH_GET_WILDCARD_SOCKADDR WSHGetWildcardSockaddr
Definition: helpers.h:29
DWORD dwProviderFlags
Definition: winsock2.h:684
Definition: winsock.h:66
#define WSAENOTSOCK
Definition: winerror.h:1951
SOCKET fd_array[FD_SETSIZE]
Definition: winsock.h:68
#define AFD_SHARE_UNIQUE
Definition: shared.h:191
signed char * PCHAR
Definition: retypes.h:7
#define SOCKET_ERROR
Definition: winsock.h:333
INT WSPAPI WSPCloseSocket(IN SOCKET Handle, OUT LPINT lpErrno)
Definition: dllmain.c:623
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
INT WSPAPI WSPRecvDisconnect(IN SOCKET s, OUT LPWSABUF lpInboundDisconnectData, OUT LPINT lpErrno)
Definition: sndrcv.c:919
#define STATUS_INVALID_CONNECTION
Definition: ntstatus.h:542
#define STATUS_PROTOCOL_NOT_SUPPORTED
Definition: ntstatus.h:958
INT AddressFamily
Definition: msafd.h:56
GLint level
Definition: gl.h:1546
#define IN
Definition: typedefs.h:38
int(CALLBACK * LPCONDITIONPROC)(IN LPWSABUF lpCallerId, IN LPWSABUF lpCallerData, IN OUT LPQOS lpSQOS, IN OUT LPQOS lpGQOS, IN LPWSABUF lpCalleeId, IN LPWSABUF lpCalleeData, OUT GROUP FAR *g, IN DWORD_PTR dwCallbackData)
Definition: winsock2.h:711
_In_opt_ HANDLE _In_opt_ PIO_APC_ROUTINE _In_opt_ PVOID ApcContext
Definition: iofuncs.h:719
#define XP1_MESSAGE_ORIENTED
Definition: winsock2.h:439
VOID WINAPI GetSystemTimeAsFileTime(OUT PFILETIME lpFileTime)
Definition: time.c:128
HANDLE SockEvent
#define SIOCATMARK
Definition: winsock.h:253
DWORD SequenceNumber
Definition: msafd.h:131
TRANSPORT_ADDRESS Address
Definition: shared.h:70
#define _Must_inspect_result_
Definition: no_sal2.h:314
BOOLEAN Listening
Definition: msafd.h:68
VOID SockProcessAsyncSelect(PSOCKET_INFORMATION Socket, PASYNC_DATA AsyncData)
Definition: dllmain.c:3866
IN PCO_ADDRESS_FAMILY AddressFamily
Definition: ndis.h:1906
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:790
#define IOCTL_AFD_BIND
Definition: shared.h:267
BOOLEAN RejectConnection
Definition: shared.h:81
VOID(* PIO_APC_ROUTINE)(IN PVOID ApcContext, IN PIO_STATUS_BLOCK IoStatusBlock, IN ULONG Reserved)
Definition: nt_native.h:877
BOOL WSPAPI WSPAcceptEx(IN SOCKET sListenSocket, IN SOCKET sAcceptSocket, OUT PVOID lpOutputBuffer, IN DWORD dwReceiveDataLength, IN DWORD dwLocalAddressLength, IN DWORD dwRemoteAddressLength, OUT LPDWORD lpdwBytesReceived, IN OUT LPOVERLAPPED lpOverlapped)
Definition: stubs.c:58
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define WSAEFAULT
Definition: winerror.h:1945
SOCKADDR WSRemoteAddress
Definition: msafd.h:95
#define IO_COMPLETION_ALL_ACCESS
Definition: file.c:72
NTSTATUS NTAPI NtSetInformationFile(HANDLE hFile, PIO_STATUS_BLOCK io, PVOID ptr, ULONG len, FILE_INFORMATION_CLASS FileInformationClass)
DWORD CatalogEntryId
Definition: dllmain.c:21
BOOLEAN ExclusiveAddressUse
Definition: msafd.h:73
#define FILE_OPEN_IF
Definition: from_kernel.h:56
UCHAR Address[1]
Definition: tdi.h:340
#define MapViewOfFile
Definition: compat.h:410
#define AFD_EVENT_CONNECT_FAIL
Definition: shared.h:211
#define error(str)
Definition: mkdosfs.c:1605
BOOLEAN Boolean
Definition: shared.h:33
INT WSPAPI WSPEnumNetworkEvents(IN SOCKET Handle, IN WSAEVENT hEventObject, OUT LPWSANETWORKEVENTS lpNetworkEvents, OUT LPINT lpErrno)
Definition: event.c:133
#define LOBYTE(W)
Definition: jmemdos.c:487
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:225
#define DbgPrint
Definition: loader.c:25
BOOLEAN SockGetAsyncSelectHelperAfdHandle(VOID)
Definition: dllmain.c:3675
#define _Out_writes_bytes_to_opt_(size, count)
Definition: no_sal2.h:375
#define FD_ACCEPT
Definition: winsock.h:408
VOID SockReenableAsyncSelectEvent(IN PSOCKET_INFORMATION Socket, IN ULONG Event)
Definition: dllmain.c:3983
#define MAKEWORD(a, b)
Definition: typedefs.h:247
#define FD_CONNECT
Definition: winsock.h:409
struct _AFD_HANDLE_ AFD_HANDLE
#define WSA_OPERATION_ABORTED
Definition: winsock2.h:594
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define DLL_THREAD_ATTACH
Definition: compat.h:121
BOOL WSPAPI WSPGetOverlappedResult(IN SOCKET Handle, IN LPWSAOVERLAPPED lpOverlapped, OUT LPDWORD lpdwBytes, IN BOOL fWait, OUT LPDWORD lpdwFlags, OUT LPINT lpErrno)
Definition: sndrcv.c:96
#define AFD_ENDPOINT_C_ROOT
Definition: shared.h:157
#define AFD_EVENT_DISCONNECT
Definition: shared.h:206
#define WSAEINVAL
Definition: winerror.h:1946
ULONG ConnectTime
Definition: msafd.h:66
BOOLEAN UseDelayedAcceptance
Definition: shared.h:46
char CHAR
Definition: xmlstorage.h:175
PSOCKET_INFORMATION GetSocketStructure(SOCKET Handle)
Definition: dllmain.c:3507
#define WSAEAFNOSUPPORT
Definition: winerror.h:1960
SOCKADDR WSLocalAddress
Definition: msafd.h:94
#define WARN(fmt,...)
Definition: debug.h:111
int notify
Definition: msacm.c:1365
#define SO_OOBINLINE
Definition: winsock.h:186
SOCKET Handle
Definition: msafd.h:99
LONG NTSTATUS
Definition: precomp.h:26
#define INT
Definition: polytest.cpp:20
#define HandleToUlong(h)
Definition: basetsd.h:79
HANDLE SockAsyncCompletionPort
Definition: dllmain.c:28
#define WSH_NOTIFY_BIND
Definition: wsahelp.h:10
struct _AFD_RECEIVED_ACCEPT_DATA * PAFD_RECEIVED_ACCEPT_DATA
#define AFD_EVENT_ABORT
Definition: shared.h:207
_In_ USHORT _In_ ULONG Protocol
Definition: wsk.h:182
BOOLEAN Broadcast
Definition: msafd.h:69
#define SO_PROTOCOL_INFOW
Definition: winsock2.h:249
#define CreateFileMapping
Definition: winbase.h:3584
#define WSAEWOULDBLOCK
Definition: winerror.h:1948
#define HIBYTE(W)
Definition: jmemdos.c:486
#define SO_KEEPALIVE
Definition: winsock.h:181
BOOLEAN OobInline
Definition: msafd.h:71
NTSTATUS NTAPI NtCreateEvent(OUT PHANDLE EventHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN EVENT_TYPE EventType, IN BOOLEAN InitialState)
Definition: event.c:100
struct _AFDAPCCONTEXT * PAFDAPCCONTEXT
BOOL WINAPI DisableThreadLibraryCalls(IN HMODULE hLibModule)
Definition: loader.c:85
#define SIO_GET_EXTENSION_FUNCTION_POINTER
Definition: ws2def.h:167
DWORD dwServiceFlags3
Definition: winsock2.h:682
INT WSPAPI WSPAsyncSelect(IN SOCKET Handle, IN HWND hWnd, IN UINT wMsg, IN LONG lEvent, OUT LPINT lpErrno)
Definition: sndrcv.c:17
BOOLEAN SendShutdown
Definition: msafd.h:77
#define INVALID_HANDLE_VALUE
Definition: compat.h:399
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:733
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define CF_REJECT
Definition: winsock2.h:414
GLuint buffer
Definition: glext.h:5915
_In_ BOOL _In_ HANDLE hProcess
Definition: mapping.h:70
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
#define XP1_QOS_SUPPORTED
Definition: winsock2.h:449
#define IOCTL_AFD_START_LISTEN
Definition: shared.h:271
BOOLEAN UseDelayedAcceptance
Definition: msafd.h:78
#define WSH_NOTIFY_ACCEPT
Definition: wsahelp.h:13
DWORD SequenceNumber
Definition: msafd.h:90
#define IOCTL_AFD_GET_PENDING_CONNECT_DATA
Definition: shared.h:333
#define WSA_FLAG_MULTIPOINT_D_ROOT
Definition: winsock2.h:469
BOOL WSPAPI WSPGetQOSByName(IN SOCKET s, IN OUT LPWSABUF lpQOSName, OUT LPQOS lpQOS, OUT LPINT lpErrno)
Definition: stubs.c:26
#define DLL_PROCESS_ATTACH
Definition: compat.h:120
#define FD_READ
Definition: winsock.h:405
_IRQL_requires_same_ typedef _In_ ULONG _In_ UCHAR Level
Definition: wmitypes.h:55
LARGE_INTEGER Timeout
Definition: shared.h:56
Definition: dhcpd.h:245
#define SO_CONDITIONAL_ACCEPT
Definition: ws2def.h:121
NTSYSAPI NTSTATUS NTAPI NtDeviceIoControlFile(IN HANDLE hFile, IN HANDLE hEvent OPTIONAL, IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL, IN PVOID IoApcContext OPTIONAL, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN ULONG DeviceIoControlCode, IN PVOID InBuffer OPTIONAL, IN ULONG InBufferLength, OUT PVOID OutBuffer OPTIONAL, IN ULONG OutBufferLength)
_Check_return_ long __cdecl wcstol(_In_z_ const wchar_t *_Str, _Out_opt_ _Deref_post_z_ wchar_t **_EndPtr, _In_ int _Radix)
#define WSAID_GETACCEPTEXSOCKADDRS
Definition: mswsock.h:77
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
BOOL WINAPI DllMain(HINSTANCE hDLLInst, DWORD fdwReason, LPVOID lpvReserved)
Definition: dllmain.c:52
#define SOL_SOCKET
Definition: winsock.h:398
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
#define SO_LINGER
Definition: winsock.h:185
#define WSAEACCES
Definition: winerror.h:1944
#define FD_ZERO(set)
Definition: winsock.h:96
#define FD_SET(fd, set)
Definition: winsock.h:89
#define IOCTL_AFD_WAIT_FOR_LISTEN
Definition: shared.h:273
#define NO_ERROR
Definition: dderror.h:5
#define BOOL
Definition: nt_native.h:43
DWORD GetCurrentTimeInSeconds(VOID)
Definition: dllmain.c:1417
#define WSAENOPROTOOPT
Definition: winerror.h:1955
u_int fd_count
Definition: winsock.h:67
#define DWORD
Definition: nt_native.h:44
BOOLEAN SockCreateOrReferenceAsyncThread(VOID)
Definition: dllmain.c:3580
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)
Definition: dllmain.c:3257
int32_t INT
Definition: typedefs.h:56
char sa_data[14]
Definition: winsock.h:218
#define FD_OOB
Definition: winsock.h:407
struct GroupData GroupData
Definition: dplay_global.h:116
#define ntohs(x)
Definition: module.h:208
#define DLL_THREAD_DETACH
Definition: compat.h:122
#define STATUS_HOST_UNREACHABLE
Definition: ntstatus.h:691
#define SO_CONNECT_TIME
Definition: mswsock.h:36
LPWPUMODIFYIFSHANDLE lpWPUModifyIFSHandle
Definition: ws2spi.h:608
#define FILE_SHARE_READ
Definition: compat.h:125
#define _In_opt_
Definition: no_sal2.h:213
struct _SOCKET_INFORMATION * NextSocket
Definition: msafd.h:116
#define STATUS_ADDRESS_ALREADY_EXISTS
Definition: ntstatus.h:640
#define WSAVERNOTSUPPORTED
Definition: winerror.h:1986
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
WSAPROTOCOL_INFOW ProtocolInfo
Definition: msafd.h:115
#define SOCK_RAW
Definition: winsock.h:337
INT WSPAPI WSPCancelBlockingCall(OUT LPINT lpErrno)
Definition: stubs.c:15
DWORD CreateFlags
Definition: msafd.h:81
ULONG SizeOfHelperData
Definition: msafd.h:122
PSOCKADDR RemoteAddress
Definition: msafd.h:106
INT WSPAPI WSPCleanup(OUT LPINT lpErrno)
Definition: dllmain.c:3234
BOOLEAN ReuseAddresses
Definition: msafd.h:72
#define WSAEOPNOTSUPP
Definition: winerror.h:1958
#define STATUS_END_OF_FILE
Definition: shellext.h:67
#define SO_EXCLUSIVEADDRUSE
Definition: ws2def.h:105
#define FD_WRITE
Definition: winsock.h:406
#define AFD_EVENT_CLOSE
Definition: shared.h:208
int WSPAPI WSPRecv(SOCKET Handle, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesRead, LPDWORD ReceiveFlags, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, LPWSATHREADID lpThreadId, LPINT lpErrno)
Definition: sndrcv.c:157
#define IOCTL_AFD_DISCONNECT
Definition: shared.h:287
#define STATUS_TIMEOUT
Definition: ntstatus.h:81
DWORD dwReason
Definition: misc.cpp:154
DWORD dwServiceFlags4
Definition: winsock2.h:683
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
#define WSAMAKESELECTREPLY(e, error)
Definition: winsock.h:478
#define AFD_ENDPOINT_CONNECTIONLESS
Definition: shared.h:153
INT WSPAPI WSPDuplicateSocket(IN SOCKET Handle, IN DWORD dwProcessId, OUT LPWSAPROTOCOL_INFOW lpProtocolInfo, OUT LPINT lpErrno)
Definition: dllmain.c:449
#define FD_GROUP_QOS
Definition: winsock2.h:308
#define AFD_SHARE_WILDCARD
Definition: shared.h:193
#define THREAD_PRIORITY_ABOVE_NORMAL
Definition: winbase.h:272
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
VOID SockProcessQueuedAsyncSelect(PVOID Context, PIO_STATUS_BLOCK IoStatusBlock)
Definition: dllmain.c:3949
#define DUPLICATE_SAME_ACCESS
#define SEC_COMMIT
Definition: mmtypes.h:99
#define WSA_FLAG_MULTIPOINT_C_LEAF
Definition: winsock2.h:468
DWORD ProviderFlags
Definition: msafd.h:83
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
LARGE_INTEGER LargeInteger
Definition: shared.h:32
DWORD dwCatalogEntryId
Definition: winsock2.h:686
#define STATUS_REMOTE_DISCONNECT
Definition: ntstatus.h:538
HANDLE WINAPI GetCurrentThread(VOID)
Definition: proc.c:1148
int WSPAPI WSPSendTo(SOCKET Handle, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesSent, DWORD iFlags, const struct sockaddr *SocketAddress, int SocketAddressLength, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, LPWSATHREADID lpThreadId, LPINT lpErrno)
Definition: sndrcv.c:719
unsigned int BOOL
Definition: ntddk_ex.h:94
BOOLEAN UseSAN
Definition: msafd.h:79
long LONG
Definition: pedump.c:60
#define SO_GROUP_ID
Definition: ws2def.h:117
enum _SOCKET_STATE SOCKET_STATE
_Must_inspect_result_ int WSPAPI WSPStartup(_In_ WORD wVersionRequested, _In_ LPWSPDATA lpWSPData, _In_ LPWSAPROTOCOL_INFOW lpProtocolInfo, _In_ WSPUPCALLTABLE UpcallTable, _Out_ LPWSPPROC_TABLE lpProcTable)
Definition: dllmain.c:2985
#define EVENT_ALL_ACCESS
Definition: isotest.c:82
PSOCK_SHARED_INFO SharedData
Definition: msafd.h:100
DWORD EndpointFlags
Definition: shared.h:22
#define SO_BROADCAST
Definition: winsock.h:183
ULONG SequenceNumber
Definition: shared.h:64
#define PROCESS_DUP_HANDLE
#define GENERIC_WRITE
Definition: nt_native.h:90
NTSTATUS NTAPI NtSetInformationObject(IN HANDLE ObjectHandle, IN OBJECT_INFORMATION_CLASS ObjectInformationClass, IN PVOID ObjectInformation, IN ULONG Length)
Definition: oblife.c:1735
ULONG Events
Definition: shared.h:51
#define FAR
Definition: guiddef.h:36
#define IOCTL_AFD_SET_CONNECT_DATA_SIZE
Definition: shared.h:319
#define IOCTL_AFD_SELECT
Definition: shared.h:285
ULONG SizeOfSendBuffer
Definition: msafd.h:65
INT MaxWSAddressLength
Definition: helpers.h:17
SOCKADDR_ENDPOINT_INFO EndpointInfo
Definition: wsahelp.h:45
TRANSPORT_ADDRESS RemoteAddress
Definition: shared.h:121
#define WSH_NOTIFY_CONNECT_ERROR
Definition: wsahelp.h:18
Definition: ws2spi.h:46
unsigned char BOOLEAN
SOCKET WSPAPI WSPJoinLeaf(IN SOCKET s, IN CONST SOCKADDR *name, IN INT namelen, IN LPWSABUF lpCallerData, OUT LPWSABUF lpCalleeData, IN LPQOS lpSQOS, IN LPQOS lpGQOS, IN DWORD dwFlags, OUT LPINT lpErrno)
Definition: stubs.c:40
#define XP1_MULTIPOINT_DATA_PLANE
Definition: winsock2.h:448
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:136
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:751
smooth NULL
Definition: ftsmooth.c:416
LARGE_INTEGER Timeout
Definition: shared.h:137
#define XP1_MULTIPOINT_CONTROL_PLANE
Definition: winsock2.h:447
#define AFD_EVENT_RECEIVE
Definition: shared.h:203
#define SO_REUSEADDR
Definition: winsock.h:180
#define _Out_
Definition: no_sal2.h:323
#define FILE_MAP_ALL_ACCESS
Definition: winbase.h:156
#define SO_ERROR
Definition: winsock.h:194
PWSH_GET_SOCKADDR_TYPE WSHGetSockaddrType
Definition: helpers.h:28
DWORD SizeOfTransportName
Definition: shared.h:24
#define WSA_IO_PENDING
Definition: winsock2.h:589
#define IOCTL_AFD_SET_CONNECT_DATA
Definition: shared.h:303
_Reserved_ PVOID Reserved
Definition: winddi.h:3974
PHELPER_DATA HelperData
Definition: msafd.h:103
Definition: bufpool.h:45
#define AFD_ENDPOINT_D_ROOT
Definition: shared.h:158
#define AFD_EVENT_CONNECT
Definition: shared.h:209
LPWPUCOMPLETEOVERLAPPEDREQUEST lpWPUCompleteOverlappedRequest
Definition: dllmain.c:22
AFD_POLL_INFO AsyncSelectInfo
Definition: msafd.h:133
#define CF_ACCEPT
Definition: winsock2.h:413
void * PVOID
Definition: retypes.h:9
BOOLEAN UseDelayedAcceptance
Definition: helpers.h:20
#define WSAETIMEDOUT
Definition: winerror.h:1973
#define AF_UNSPEC
Definition: winsock.h:344
#define AFD_INFO_BLOCKING_MODE
Definition: shared.h:183
#define ULL(a, b)
Definition: format_msg.c:27
#define UlongToPtr(u)
Definition: config.h:106
BOOL WINAPI SetThreadPriority(IN HANDLE hThread, IN int nPriority)
Definition: thread.c:699
#define SO_MAX_MSG_SIZE
Definition: ws2def.h:119
#define AFD_DISCONNECT_SEND
Definition: shared.h:197
#define DLL_PROCESS_DETACH
Definition: compat.h:119
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define AFD_EVENT_SEND
Definition: shared.h:205
#define AFD_INFO_SEND_WINDOW_SIZE
Definition: shared.h:186
BOOLEAN ReceiveShutdown
Definition: msafd.h:76
#define AFD_INFO_RECEIVE_CONTENT_SIZE
Definition: shared.h:188
int WSPAPI WSPListen(SOCKET Handle, int Backlog, LPINT lpErrno)
Definition: dllmain.c:981
BOOLEAN Debug
Definition: msafd.h:70
LONG RefCount
Definition: msafd.h:55
#define IOCTL_AFD_CONNECT
Definition: shared.h:269
BOOLEAN NonBlocking
Definition: msafd.h:74
_In_ HANDLE Handle
Definition: extypes.h:390
GLboolean GLboolean g
Definition: glext.h:6204
#define IOCTL_AFD_SET_INFO
Definition: shared.h:295
DWORD ServiceFlags1
Definition: msafd.h:82
#define SO_RCVTIMEO
Definition: winsock.h:193
#define AFD_EVENT_ACCEPT
Definition: shared.h:210
#define TRACE(s)
Definition: solgame.cpp:4
DWORD HelperEvents
Definition: msafd.h:102
GLsizeiptr size
Definition: glext.h:5919
#define IOCTL_AFD_DEFER_ACCEPT
Definition: shared.h:331
#define IS_INTRESOURCE(i)
Definition: winuser.h:580
INT SocketType
Definition: msafd.h:57
#define GetProcessHeap()
Definition: compat.h:403
GROUP GroupID
Definition: msafd.h:84
#define FD_CLOSE
Definition: winsock.h:410
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
NTSTATUS NTAPI NtCreateFile(OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PLARGE_INTEGER AllocationSize OPTIONAL, IN ULONG FileAttributes, IN ULONG ShareAccess, IN ULONG CreateDisposition, IN ULONG CreateOptions, IN PVOID EaBuffer OPTIONAL, IN ULONG EaLength)
#define INVALID_SOCKET
Definition: winsock.h:332
struct _TRANSPORT_ADDRESS TRANSPORT_ADDRESS
_CONST_RETURN wchar_t *__cdecl wcschr(_In_z_ const wchar_t *_Str, wchar_t _Ch)
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define SO_RCVBUF
Definition: winsock.h:189
INT WSPAPI WSPGetSockName(IN SOCKET Handle, OUT LPSOCKADDR Name, IN OUT LPINT NameLength, OUT LPINT lpErrno)
Definition: dllmain.c:2152
#define WSA_FLAG_MULTIPOINT_D_LEAF
Definition: winsock2.h:470
__wchar_t WCHAR
Definition: xmlstorage.h:180
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
#define IOCTL_AFD_GET_PEER_NAME
Definition: shared.h:291
ULONG InformationClass
Definition: shared.h:29
uint64_t ULONGLONG
Definition: typedefs.h:65
#define UlongToHandle(ul)
Definition: basetsd.h:97
int SockGetTdiName(PINT AddressFamily, PINT SocketType, PINT Protocol, GROUP Group, DWORD Flags, PUNICODE_STRING TransportName, PVOID *HelperDllContext, PHELPER_DATA *HelperDllData, PDWORD Events)
Definition: helpers.c:22
#define IOCTL_AFD_GET_SOCK_NAME
Definition: shared.h:289
HANDLE WINAPI GetCurrentProcess(VOID)
Definition: proc.c:1138
#define OBJ_INHERIT
Definition: winternl.h:225
SOCKET WSPAPI WSPSocket(int AddressFamily, int SocketType, int Protocol, LPWSAPROTOCOL_INFOW lpProtocolInfo, GROUP g, DWORD dwFlags, LPINT lpErrno)
Definition: dllmain.c:48
ULONG len
Definition: ws2def.h:519
#define swprintf(buf, format,...)
Definition: sprintf.c:56
#define WINAPI
Definition: msvc.h:6
#define AFD_ENDPOINT_MULTIPOINT
Definition: shared.h:156
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
LPWSAOVERLAPPED lpOverlapped
Definition: msafd.h:138
unsigned int GROUP
Definition: winsock2.h:640
PWSH_NOTIFY WSHNotify
Definition: helpers.h:25
#define BufferSize
Definition: classpnp.h:419
unsigned short WORD
Definition: ntddk_ex.h:93
#define SO_DONTLINGER
Definition: winsock.h:187
PVOID HANDLE
Definition: typedefs.h:71
unsigned long DWORD
Definition: ntddk_ex.h:95
#define WSAEHOSTUNREACH
Definition: winerror.h:1978
#define WSAENETDOWN
Definition: winerror.h:1963
INT SizeOfRemoteAddress
Definition: msafd.h:60
FORCEINLINE DWORD MsafdReturnWithErrno(NTSTATUS Status, LPINT Errno, DWORD Received, LPDWORD ReturnedBytes)
Definition: msafd.h:546
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
LONG TAAddressCount
Definition: tdi.h:376
struct _IO_STATUS_BLOCK * PIO_STATUS_BLOCK
Definition: change.c:34
int WSPAPI WSPShutdown(SOCKET Handle, int HowTo, LPINT lpErrno)
Definition: dllmain.c:2072
NTSTATUS NTAPI NtSetIoCompletion(IN HANDLE IoCompletionPortHandle, IN PVOID CompletionKey, IN PVOID CompletionContext, IN NTSTATUS CompletionStatus, IN ULONG CompletionInformation)
Definition: iocomp.c:568
INT WSPAPI WSPSendDisconnect(IN SOCKET s, IN LPWSABUF lpOutboundDisconnectData, OUT LPINT lpErrno)
Definition: sndrcv.c:931
union _AFD_INFO::@3282 Information
PSOCKET_INFORMATION ParentSocket
Definition: msafd.h:130
static IUnknown Object
Definition: main.c:512
int WSPAPI WSPEventSelect(IN SOCKET Handle, IN WSAEVENT hEventObject, IN long lNetworkEvents, OUT LPINT lpErrno)
Definition: event.c:17
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3399
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define XP1_PSEUDO_STREAM
Definition: winsock2.h:440
LIST_ENTRY SockHelpersListHead
Definition: dllmain.c:25
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define WSAEMSGSIZE
Definition: winerror.h:1953
int WSPAPI WSPSend(SOCKET Handle, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesSent, DWORD iFlags, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, LPWSATHREADID lpThreadId, LPINT lpErrno)
Definition: sndrcv.c:568
unsigned char UCHAR
Definition: xmlstorage.h:181
int WSPAPI WSPRecvFrom(SOCKET Handle, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesRead, LPDWORD ReceiveFlags, struct sockaddr *SocketAddress, int *SocketAddressLength, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, LPWSATHREADID lpThreadId, LPINT lpErrno)
Definition: sndrcv.c:351
#define AFD_DISCONNECT_ABORT
Definition: shared.h:199
VOID WSPAPI WSPGetAcceptExSockaddrs(IN PVOID lpOutputBuffer, IN DWORD dwReceiveDataLength, IN DWORD dwLocalAddressLength, IN DWORD dwRemoteAddressLength, OUT struct sockaddr **LocalSockaddr, OUT LPINT LocalSockaddrLength, OUT struct sockaddr **RemoteSockaddr, OUT LPINT RemoteSockaddrLength)
Definition: stubs.c:104
char * PBOOLEAN
Definition: retypes.h:11
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)