ReactOS  0.4.13-dev-52-g0efcfec
sndrcv.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/sndrcv.c
5  * PURPOSE: Send/receive routines
6  * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7  * Alex Ionescu (alex@relsoft.net)
8  * REVISIONS:
9  * CSH 01/09-2000 Created
10  * Alex 16/07/2004 - Complete Rewrite
11  */
12 
13 #include <msafd.h>
14 
15 INT
16 WSPAPI
18  IN HWND hWnd,
19  IN UINT wMsg,
20  IN LONG lEvent,
21  OUT LPINT lpErrno)
22 {
23  PSOCKET_INFORMATION Socket = NULL;
24  PASYNC_DATA AsyncData;
25  BOOLEAN BlockMode;
26 
27  /* Get the Socket Structure associated to this Socket */
28  Socket = GetSocketStructure(Handle);
29  if (!Socket)
30  {
31  *lpErrno = WSAENOTSOCK;
32  return SOCKET_ERROR;
33  }
34 
35  /* Allocate the Async Data Structure to pass on to the Thread later */
36  AsyncData = HeapAlloc(GetProcessHeap(), 0, sizeof(*AsyncData));
37  if (!AsyncData)
38  {
40  return INVALID_SOCKET;
41  }
42 
43  /* Change the Socket to Non Blocking */
44  BlockMode = TRUE;
46  Socket->SharedData->NonBlocking = TRUE;
47 
48  /* Deactivate WSPEventSelect */
49  if (Socket->SharedData->AsyncEvents)
50  {
51  if (WSPEventSelect(Handle, NULL, 0, lpErrno) == SOCKET_ERROR)
52  {
53  HeapFree(GetProcessHeap(), 0, AsyncData);
54  return SOCKET_ERROR;
55  }
56  }
57 
58  /* Create the Asynch Thread if Needed */
60 
61  /* Open a Handle to AFD's Async Helper */
63 
64  /* Store Socket Data */
65  Socket->SharedData->hWnd = hWnd;
66  Socket->SharedData->wMsg = wMsg;
67  Socket->SharedData->AsyncEvents = lEvent;
68  Socket->SharedData->AsyncDisabledEvents = 0;
69  Socket->SharedData->SequenceNumber++;
70 
71  /* Return if there are no more Events */
72  if ((Socket->SharedData->AsyncEvents & (~Socket->SharedData->AsyncDisabledEvents)) == 0)
73  {
74  HeapFree(GetProcessHeap(), 0, AsyncData);
75  return 0;
76  }
77 
78  /* Set up the Async Data */
79  AsyncData->ParentSocket = Socket;
80  AsyncData->SequenceNumber = Socket->SharedData->SequenceNumber;
81 
82  /* Begin Async Select by using I/O Completion */
85  AsyncData,
86  0,
87  0);
88 
89  /* Return */
90  return ERROR_SUCCESS;
91 }
92 
93 
94 BOOL
95 WSPAPI
99  OUT LPDWORD lpdwBytes,
100  IN BOOL fWait,
101  OUT LPDWORD lpdwFlags,
102  OUT LPINT lpErrno)
103 {
104  PSOCKET_INFORMATION Socket;
105  BOOL Ret;
106 
107  TRACE("Called (%x)\n", Handle);
108 
109  /* Get the Socket Structure associate to this Socket*/
110  Socket = GetSocketStructure(Handle);
111  if (!Socket)
112  {
113  if(lpErrno)
114  *lpErrno = WSAENOTSOCK;
115  return FALSE;
116  }
117  if (!lpOverlapped || !lpdwBytes || !lpdwFlags)
118  {
119  if (lpErrno)
120  *lpErrno = WSAEFAULT;
121  return FALSE;
122  }
123  Ret = GetOverlappedResult((HANDLE)Handle, lpOverlapped, lpdwBytes, fWait);
124 
125  if (Ret)
126  {
127  *lpdwFlags = 0;
128 
129  /* Re-enable Async Event */
133  }
134 
135  return Ret;
136 }
137 
138 VOID
139 NTAPI
142  ULONG Reserved)
143 {
145 
146  /* Re-enable Async Event */
150 
151  Context->lpCompletionRoutine(IoStatusBlock->Status, IoStatusBlock->Information, Context->lpOverlapped, 0);
153 }
154 
155 int
156 WSPAPI
158  LPWSABUF lpBuffers,
159  DWORD dwBufferCount,
160  LPDWORD lpNumberOfBytesRead,
161  LPDWORD ReceiveFlags,
163  LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
164  LPWSATHREADID lpThreadId,
165  LPINT lpErrno)
166 {
167  PIO_STATUS_BLOCK IOSB;
168  IO_STATUS_BLOCK DummyIOSB;
169  AFD_RECV_INFO RecvInfo;
171  PVOID APCContext;
172  PIO_APC_ROUTINE APCFunction;
173  HANDLE Event = NULL;
175  PSOCKET_INFORMATION Socket;
176 
177  TRACE("Called (%x)\n", Handle);
178 
179  /* Get the Socket Structure associate to this Socket*/
180  Socket = GetSocketStructure(Handle);
181  if (!Socket)
182  {
183  if (lpErrno)
184  *lpErrno = WSAENOTSOCK;
185  return SOCKET_ERROR;
186  }
187  if (!lpNumberOfBytesRead && !lpOverlapped)
188  {
189  if (lpErrno)
190  *lpErrno = WSAEFAULT;
191  return SOCKET_ERROR;
192  }
193  if (Socket->SharedData->OobInline && ReceiveFlags && (*ReceiveFlags & MSG_OOB) != 0)
194  {
195  if (lpErrno)
196  *lpErrno = WSAEINVAL;
197  return SOCKET_ERROR;
198  }
199 
202 
203  if( !NT_SUCCESS(Status) )
204  return -1;
205 
206  /* Set up the Receive Structure */
207  RecvInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
208  RecvInfo.BufferCount = dwBufferCount;
209  RecvInfo.TdiFlags = 0;
210  RecvInfo.AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0;
211 
212  /* Set the TDI Flags */
213  if (*ReceiveFlags == 0)
214  {
215  RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL;
216  }
217  else
218  {
219  if (*ReceiveFlags & MSG_OOB)
220  {
221  RecvInfo.TdiFlags |= TDI_RECEIVE_EXPEDITED;
222  }
223 
224  if (*ReceiveFlags & MSG_PEEK)
225  {
226  RecvInfo.TdiFlags |= TDI_RECEIVE_PEEK;
227  }
228 
229  if (*ReceiveFlags & MSG_PARTIAL)
230  {
231  RecvInfo.TdiFlags |= TDI_RECEIVE_PARTIAL;
232  }
233  }
234 
235  /* Verify if we should use APC */
236 
237  if (lpOverlapped == NULL)
238  {
239  /* Not using Overlapped structure, so use normal blocking on event */
240  APCContext = NULL;
241  APCFunction = NULL;
242  Event = SockEvent;
243  IOSB = &DummyIOSB;
244  }
245  else
246  {
247  /* Overlapped request for non overlapped opened socket */
248  if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0)
249  {
250  TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
251  return MsafdReturnWithErrno(0, lpErrno, 0, lpNumberOfBytesRead);
252  }
253  if (lpCompletionRoutine == NULL)
254  {
255  /* Using Overlapped Structure, but no Completion Routine, so no need for APC */
256  APCContext = lpOverlapped;
257  APCFunction = NULL;
258  Event = lpOverlapped->hEvent;
259  }
260  else
261  {
262  /* Using Overlapped Structure and a Completion Routine, so use an APC */
263  APCFunction = &AfdAPC; // should be a private io completion function inside us
264  APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT));
265  if (!APCContext)
266  {
267  ERR("Not enough memory for APC Context\n");
268  return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, lpNumberOfBytesRead);
269  }
270  ((PAFDAPCCONTEXT)APCContext)->lpCompletionRoutine = lpCompletionRoutine;
271  ((PAFDAPCCONTEXT)APCContext)->lpOverlapped = lpOverlapped;
272  ((PAFDAPCCONTEXT)APCContext)->lpSocket = Socket;
273  RecvInfo.AfdFlags |= AFD_SKIP_FIO;
274  }
275 
276  IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal;
277  RecvInfo.AfdFlags |= AFD_OVERLAPPED;
278  }
279 
280  IOSB->Status = STATUS_PENDING;
281 
282  /* Send IOCTL */
284  Event,
285  APCFunction,
286  APCContext,
287  IOSB,
289  &RecvInfo,
290  sizeof(RecvInfo),
291  NULL,
292  0);
293 
294  /* Wait for completion of not overlapped */
295  if (Status == STATUS_PENDING && lpOverlapped == NULL)
296  {
297  /* It's up to the protocol to time out recv. We must wait
298  * until the protocol decides it's had enough.
299  */
301  Status = IOSB->Status;
302  }
303 
304  NtClose( SockEvent );
305 
306  TRACE("Status %x Information %d\n", Status, IOSB->Information);
307 
308  if (Status == STATUS_PENDING)
309  {
310  TRACE("Leaving (Pending)\n");
311  return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesRead);
312  }
313 
314  /* Return the Flags */
315  *ReceiveFlags = 0;
316 
317  switch (Status)
318  {
320  *ReceiveFlags = MSG_OOB;
321  break;
323  *ReceiveFlags = MSG_PARTIAL | MSG_OOB;
324  break;
326  *ReceiveFlags = MSG_PARTIAL;
327  break;
328  }
329 
330  /* Re-enable Async Event */
331  if (*ReceiveFlags & MSG_OOB)
332  {
334  }
335  else
336  {
338  }
339 
340  if (Status == STATUS_SUCCESS && lpOverlapped && lpCompletionRoutine)
341  {
342  lpCompletionRoutine(Status, IOSB->Information, lpOverlapped, *ReceiveFlags);
343  HeapFree(GlobalHeap, 0, (PVOID)APCContext);
344  }
345 
346  return MsafdReturnWithErrno ( Status, lpErrno, IOSB->Information, lpNumberOfBytesRead );
347 }
348 
349 int
350 WSPAPI
352  LPWSABUF lpBuffers,
353  DWORD dwBufferCount,
354  LPDWORD lpNumberOfBytesRead,
355  LPDWORD ReceiveFlags,
356  struct sockaddr *SocketAddress,
357  int *SocketAddressLength,
359  LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
360  LPWSATHREADID lpThreadId,
361  LPINT lpErrno )
362 {
363  PIO_STATUS_BLOCK IOSB;
364  IO_STATUS_BLOCK DummyIOSB;
365  AFD_RECV_INFO_UDP RecvInfo;
367  PVOID APCContext;
368  PVOID APCFunction;
369  HANDLE Event = NULL;
371  PSOCKET_INFORMATION Socket;
372 
373  /* Get the Socket Structure associate to this Socket*/
374  Socket = GetSocketStructure(Handle);
375  if (!Socket)
376  {
377  if (lpErrno)
378  *lpErrno = WSAENOTSOCK;
379  return SOCKET_ERROR;
380  }
381  if (!lpNumberOfBytesRead && !lpOverlapped)
382  {
383  if (lpErrno)
384  *lpErrno = WSAEFAULT;
385  return SOCKET_ERROR;
386  }
387  if (Socket->SharedData->OobInline && ReceiveFlags && (*ReceiveFlags & MSG_OOB) != 0)
388  {
389  if (lpErrno)
390  *lpErrno = WSAEINVAL;
391  return SOCKET_ERROR;
392  }
393 
394  if (!(Socket->SharedData->ServiceFlags1 & XP1_CONNECTIONLESS))
395  {
396  /* Call WSPRecv for a non-datagram socket */
397  return WSPRecv(Handle,
398  lpBuffers,
399  dwBufferCount,
400  lpNumberOfBytesRead,
401  ReceiveFlags,
402  lpOverlapped,
403  lpCompletionRoutine,
404  lpThreadId,
405  lpErrno);
406  }
407 
408  /* Bind us First */
409  if (Socket->SharedData->State == SocketOpen)
410  {
412  SocketAddress,
413  SocketAddressLength);
414  /* Bind it */
415  if (WSPBind(Handle, SocketAddress, *SocketAddressLength, lpErrno) == SOCKET_ERROR)
416  return SOCKET_ERROR;
417  }
418 
421 
422  if( !NT_SUCCESS(Status) )
423  return -1;
424 
425  /* Set up the Receive Structure */
426  RecvInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
427  RecvInfo.BufferCount = dwBufferCount;
428  RecvInfo.TdiFlags = 0;
429  RecvInfo.AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0;
430  RecvInfo.AddressLength = SocketAddressLength;
431  RecvInfo.Address = SocketAddress;
432 
433  /* Set the TDI Flags */
434  if (*ReceiveFlags == 0)
435  {
436  RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL;
437  }
438  else
439  {
440  if (*ReceiveFlags & MSG_OOB)
441  {
442  RecvInfo.TdiFlags |= TDI_RECEIVE_EXPEDITED;
443  }
444 
445  if (*ReceiveFlags & MSG_PEEK)
446  {
447  RecvInfo.TdiFlags |= TDI_RECEIVE_PEEK;
448  }
449 
450  if (*ReceiveFlags & MSG_PARTIAL)
451  {
452  RecvInfo.TdiFlags |= TDI_RECEIVE_PARTIAL;
453  }
454  }
455 
456  /* Verify if we should use APC */
457 
458  if (lpOverlapped == NULL)
459  {
460  /* Not using Overlapped structure, so use normal blocking on event */
461  APCContext = NULL;
462  APCFunction = NULL;
463  Event = SockEvent;
464  IOSB = &DummyIOSB;
465  }
466  else
467  {
468  /* Overlapped request for non overlapped opened socket */
469  if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0)
470  {
471  TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
472  return MsafdReturnWithErrno(0, lpErrno, 0, lpNumberOfBytesRead);
473  }
474  if (lpCompletionRoutine == NULL)
475  {
476  /* Using Overlapped Structure, but no Completion Routine, so no need for APC */
477  APCContext = lpOverlapped;
478  APCFunction = NULL;
479  Event = lpOverlapped->hEvent;
480  }
481  else
482  {
483  /* Using Overlapped Structure and a Completion Routine, so use an APC */
484  APCFunction = &AfdAPC; // should be a private io completion function inside us
485  APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT));
486  if (!APCContext)
487  {
488  ERR("Not enough memory for APC Context\n");
489  return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, lpNumberOfBytesRead);
490  }
491  ((PAFDAPCCONTEXT)APCContext)->lpCompletionRoutine = lpCompletionRoutine;
492  ((PAFDAPCCONTEXT)APCContext)->lpOverlapped = lpOverlapped;
493  ((PAFDAPCCONTEXT)APCContext)->lpSocket = Socket;
494  RecvInfo.AfdFlags |= AFD_SKIP_FIO;
495  }
496 
497  IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal;
498  RecvInfo.AfdFlags |= AFD_OVERLAPPED;
499  }
500 
501  IOSB->Status = STATUS_PENDING;
502 
503  /* Send IOCTL */
505  Event,
506  APCFunction,
507  APCContext,
508  IOSB,
510  &RecvInfo,
511  sizeof(RecvInfo),
512  NULL,
513  0);
514 
515  /* Wait for completion of not overlapped */
516  if (Status == STATUS_PENDING && lpOverlapped == NULL)
517  {
518  WaitForSingleObject(SockEvent, INFINITE); // BUGBUG, shouldn wait infinitely for receive...
519  Status = IOSB->Status;
520  }
521 
522  NtClose( SockEvent );
523 
524  if (Status == STATUS_PENDING)
525  {
526  TRACE("Leaving (Pending)\n");
527  return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesRead);
528  }
529 
530  /* Return the Flags */
531  *ReceiveFlags = 0;
532 
533  switch (Status)
534  {
536  *ReceiveFlags = MSG_OOB;
537  break;
539  *ReceiveFlags = MSG_PARTIAL | MSG_OOB;
540  break;
542  *ReceiveFlags = MSG_PARTIAL;
543  break;
544  }
545 
546  /* Re-enable Async Event */
547  if (*ReceiveFlags & MSG_OOB)
548  {
550  }
551  else
552  {
554  }
555 
556  if (Status == STATUS_SUCCESS && lpOverlapped && lpCompletionRoutine)
557  {
558  lpCompletionRoutine(Status, IOSB->Information, lpOverlapped, *ReceiveFlags);
559  HeapFree(GlobalHeap, 0, (PVOID)APCContext);
560  }
561 
562  return MsafdReturnWithErrno ( Status, lpErrno, IOSB->Information, lpNumberOfBytesRead );
563 }
564 
565 
566 int
567 WSPAPI
569  LPWSABUF lpBuffers,
570  DWORD dwBufferCount,
571  LPDWORD lpNumberOfBytesSent,
572  DWORD iFlags,
574  LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
575  LPWSATHREADID lpThreadId,
576  LPINT lpErrno)
577 {
578  PIO_STATUS_BLOCK IOSB;
579  IO_STATUS_BLOCK DummyIOSB;
580  AFD_SEND_INFO SendInfo;
582  PVOID APCContext;
583  PVOID APCFunction;
584  HANDLE Event = NULL;
586  PSOCKET_INFORMATION Socket;
587 
588  /* Get the Socket Structure associate to this Socket*/
589  Socket = GetSocketStructure(Handle);
590  if (!Socket)
591  {
592  if (lpErrno)
593  *lpErrno = WSAENOTSOCK;
594  return SOCKET_ERROR;
595  }
596  if (!lpNumberOfBytesSent && !lpOverlapped)
597  {
598  if (lpErrno)
599  *lpErrno = WSAEFAULT;
600  return SOCKET_ERROR;
601  }
602 
605 
606  if( !NT_SUCCESS(Status) )
607  return -1;
608 
609  TRACE("Called\n");
610 
611  /* Set up the Send Structure */
612  SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
613  SendInfo.BufferCount = dwBufferCount;
614  SendInfo.TdiFlags = 0;
615  SendInfo.AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0;
616 
617  /* Set the TDI Flags */
618  if (iFlags)
619  {
620  if (iFlags & MSG_OOB)
621  {
622  SendInfo.TdiFlags |= TDI_SEND_EXPEDITED;
623  }
624  if (iFlags & MSG_PARTIAL)
625  {
626  SendInfo.TdiFlags |= TDI_SEND_PARTIAL;
627  }
628  }
629 
630  /* Verify if we should use APC */
631  if (lpOverlapped == NULL)
632  {
633  /* Not using Overlapped structure, so use normal blocking on event */
634  APCContext = NULL;
635  APCFunction = NULL;
636  Event = SockEvent;
637  IOSB = &DummyIOSB;
638  }
639  else
640  {
641  /* Overlapped request for non overlapped opened socket */
642  if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0)
643  {
644  TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
645  return MsafdReturnWithErrno(0, lpErrno, 0, lpNumberOfBytesSent);
646  }
647  if (lpCompletionRoutine == NULL)
648  {
649  /* Using Overlapped Structure, but no Completion Routine, so no need for APC */
650  APCContext = lpOverlapped;
651  APCFunction = NULL;
652  Event = lpOverlapped->hEvent;
653  }
654  else
655  {
656  /* Using Overlapped Structure and a Completion Routine, so use an APC */
657  APCFunction = &AfdAPC; // should be a private io completion function inside us
658  APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT));
659  if (!APCContext)
660  {
661  ERR("Not enough memory for APC Context\n");
662  return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, lpNumberOfBytesSent);
663  }
664  ((PAFDAPCCONTEXT)APCContext)->lpCompletionRoutine = lpCompletionRoutine;
665  ((PAFDAPCCONTEXT)APCContext)->lpOverlapped = lpOverlapped;
666  ((PAFDAPCCONTEXT)APCContext)->lpSocket = Socket;
667  SendInfo.AfdFlags |= AFD_SKIP_FIO;
668  }
669 
670  IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal;
671  SendInfo.AfdFlags |= AFD_OVERLAPPED;
672  }
673 
674  IOSB->Status = STATUS_PENDING;
675 
676  /* Send IOCTL */
678  Event,
679  APCFunction,
680  APCContext,
681  IOSB,
683  &SendInfo,
684  sizeof(SendInfo),
685  NULL,
686  0);
687 
688  /* Wait for completion of not overlapped */
689  if (Status == STATUS_PENDING && lpOverlapped == NULL)
690  {
691  WaitForSingleObject(SockEvent, INFINITE); // BUGBUG, shouldn wait infinitely for send...
692  Status = IOSB->Status;
693  }
694 
695  NtClose( SockEvent );
696 
697  if (Status == STATUS_PENDING)
698  {
699  TRACE("Leaving (Pending)\n");
700  return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesSent);
701  }
702 
703  /* Re-enable Async Event */
705 
706  TRACE("Leaving (Success, %d)\n", IOSB->Information);
707 
708  if (Status == STATUS_SUCCESS && lpOverlapped && lpCompletionRoutine)
709  {
710  lpCompletionRoutine(Status, IOSB->Information, lpOverlapped, 0);
711  HeapFree(GlobalHeap, 0, (PVOID)APCContext);
712  }
713 
714  return MsafdReturnWithErrno( Status, lpErrno, IOSB->Information, lpNumberOfBytesSent );
715 }
716 
717 int
718 WSPAPI
720  LPWSABUF lpBuffers,
721  DWORD dwBufferCount,
722  LPDWORD lpNumberOfBytesSent,
723  DWORD iFlags,
724  const struct sockaddr *SocketAddress,
725  int SocketAddressLength,
727  LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
728  LPWSATHREADID lpThreadId,
729  LPINT lpErrno)
730 {
731  PIO_STATUS_BLOCK IOSB;
732  IO_STATUS_BLOCK DummyIOSB;
733  AFD_SEND_INFO_UDP SendInfo;
735  PVOID APCContext;
736  PVOID APCFunction;
737  HANDLE Event = NULL;
739  PSOCKADDR BindAddress = NULL;
740  INT BindAddressLength;
742  PSOCKET_INFORMATION Socket;
743 
744  /* Get the Socket Structure associate to this Socket */
745  Socket = GetSocketStructure(Handle);
746  if (!Socket)
747  {
748  if (lpErrno)
749  *lpErrno = WSAENOTSOCK;
750  return SOCKET_ERROR;
751  }
752  if (!lpNumberOfBytesSent && !lpOverlapped)
753  {
754  if (lpErrno)
755  *lpErrno = WSAEFAULT;
756  return SOCKET_ERROR;
757  }
758 
759  if (!(Socket->SharedData->ServiceFlags1 & XP1_CONNECTIONLESS))
760  {
761  /* Use WSPSend for connection-oriented sockets */
762  return WSPSend(Handle,
763  lpBuffers,
764  dwBufferCount,
765  lpNumberOfBytesSent,
766  iFlags,
767  lpOverlapped,
768  lpCompletionRoutine,
769  lpThreadId,
770  lpErrno);
771  }
772 
773  /* Bind us First */
774  if (Socket->SharedData->State == SocketOpen)
775  {
776  /* Get the Wildcard Address */
777  BindAddressLength = Socket->HelperData->MaxWSAddressLength;
778  BindAddress = HeapAlloc(GlobalHeap, 0, BindAddressLength);
779  if (!BindAddress)
780  {
782  return INVALID_SOCKET;
783  }
784 
786  BindAddress,
787  &BindAddressLength);
788  /* Bind it */
789  if (WSPBind(Handle, BindAddress, BindAddressLength, lpErrno) == SOCKET_ERROR)
790  return SOCKET_ERROR;
791  }
792 
793  RemoteAddress = HeapAlloc(GlobalHeap, 0, 0x6 + SocketAddressLength);
794  if (!RemoteAddress)
795  {
796  if (BindAddress != NULL)
797  {
798  HeapFree(GlobalHeap, 0, BindAddress);
799  }
801  }
802 
806 
807  if (!NT_SUCCESS(Status))
808  {
810  if (BindAddress != NULL)
811  {
812  HeapFree(GlobalHeap, 0, BindAddress);
813  }
814  return SOCKET_ERROR;
815  }
816 
817  /* Set up Address in TDI Format */
818  RemoteAddress->TAAddressCount = 1;
819  RemoteAddress->Address[0].AddressLength = SocketAddressLength - sizeof(SocketAddress->sa_family);
820  RtlCopyMemory(&RemoteAddress->Address[0].AddressType, SocketAddress, SocketAddressLength);
821 
822  /* Set up Structure */
823  SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
824  SendInfo.AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0;
825  SendInfo.BufferCount = dwBufferCount;
828 
829  /* Verify if we should use APC */
830  if (lpOverlapped == NULL)
831  {
832  /* Not using Overlapped structure, so use normal blocking on event */
833  APCContext = NULL;
834  APCFunction = NULL;
835  Event = SockEvent;
836  IOSB = &DummyIOSB;
837  }
838  else
839  {
840  /* Overlapped request for non overlapped opened socket */
841  if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0)
842  {
843  TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
844  return MsafdReturnWithErrno(0, lpErrno, 0, lpNumberOfBytesSent);
845  }
846  if (lpCompletionRoutine == NULL)
847  {
848  /* Using Overlapped Structure, but no Completion Routine, so no need for APC */
849  APCContext = lpOverlapped;
850  APCFunction = NULL;
851  Event = lpOverlapped->hEvent;
852  }
853  else
854  {
855  /* Using Overlapped Structure and a Completion Routine, so use an APC */
856  APCFunction = &AfdAPC; // should be a private io completion function inside us
857  APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT));
858  if (!APCContext)
859  {
860  ERR("Not enough memory for APC Context\n");
861  return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, lpNumberOfBytesSent);
862  }
863  ((PAFDAPCCONTEXT)APCContext)->lpCompletionRoutine = lpCompletionRoutine;
864  ((PAFDAPCCONTEXT)APCContext)->lpOverlapped = lpOverlapped;
865  ((PAFDAPCCONTEXT)APCContext)->lpSocket = Socket;
866  SendInfo.AfdFlags |= AFD_SKIP_FIO;
867  }
868 
869  IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal;
870  SendInfo.AfdFlags |= AFD_OVERLAPPED;
871  }
872 
873  /* Send IOCTL */
875  Event,
876  APCFunction,
877  APCContext,
878  IOSB,
880  &SendInfo,
881  sizeof(SendInfo),
882  NULL,
883  0);
884 
885  /* Wait for completion of not overlapped */
886  if (Status == STATUS_PENDING && lpOverlapped == NULL)
887  {
888  /* BUGBUG, shouldn't wait infinitely for send... */
890  Status = IOSB->Status;
891  }
892 
895  if (BindAddress != NULL)
896  {
897  HeapFree(GlobalHeap, 0, BindAddress);
898  }
899 
900  if (Status == STATUS_PENDING)
901  {
902  TRACE("Leaving (Pending)\n");
903  return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesSent);
904  }
905 
907 
908  if (Status == STATUS_SUCCESS && lpOverlapped && lpCompletionRoutine)
909  {
910  lpCompletionRoutine(Status, IOSB->Information, lpOverlapped, 0);
911  HeapFree(GlobalHeap, 0, (PVOID)APCContext);
912  }
913 
914  return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesSent);
915 }
916 
917 INT
918 WSPAPI
920  OUT LPWSABUF lpInboundDisconnectData,
921  OUT LPINT lpErrno)
922 {
924  return 0;
925 }
926 
927 
928 
929 INT
930 WSPAPI
932  IN LPWSABUF lpOutboundDisconnectData,
933  OUT LPINT lpErrno)
934 {
936  return 0;
937 }
938 
939 /* EOF */
PWSH_GET_WILDCARD_SOCKADDR WSHGetWildcardSockaddr
Definition: helpers.h:29
#define WSAENOTSOCK
Definition: winerror.h:1951
#define SOCKET_ERROR
Definition: winsock.h:333
INT WSPAPI WSPRecvDisconnect(IN SOCKET s, OUT LPWSABUF lpInboundDisconnectData, OUT LPINT lpErrno)
Definition: sndrcv.c:919
#define STATUS_RECEIVE_PARTIAL
Definition: ntstatus.h:129
ULONG AfdFlags
Definition: shared.h:94
#define IN
Definition: typedefs.h:38
_In_opt_ HANDLE _In_opt_ PIO_APC_ROUTINE _In_opt_ PVOID ApcContext
Definition: iofuncs.h:719
HANDLE SockEvent
DWORD SequenceNumber
Definition: msafd.h:131
PINT AddressLength
Definition: shared.h:97
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
VOID(* PIO_APC_ROUTINE)(IN PVOID ApcContext, IN PIO_STATUS_BLOCK IoStatusBlock, IN ULONG Reserved)
Definition: nt_native.h:877
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define WSAEFAULT
Definition: winerror.h:1945
#define TDI_RECEIVE_PARTIAL
Definition: tdi.h:121
#define ERROR_SUCCESS
Definition: deptool.c:10
#define AFD_IMMEDIATE
Definition: shared.h:220
BOOLEAN SockGetAsyncSelectHelperAfdHandle(VOID)
Definition: dllmain.c:3675
VOID SockReenableAsyncSelectEvent(IN PSOCKET_INFORMATION Socket, IN ULONG Event)
Definition: dllmain.c:3983
BOOL WINAPI GetOverlappedResult(IN HANDLE hFile, IN LPOVERLAPPED lpOverlapped, OUT LPDWORD lpNumberOfBytesTransferred, IN BOOL bWait)
Definition: iocompl.c:204
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
TDI_CONNECTION_INFORMATION TdiConnection
Definition: shared.h:112
#define WSAEINVAL
Definition: winerror.h:1946
ULONG TdiFlags
Definition: shared.h:104
PSOCKET_INFORMATION GetSocketStructure(SOCKET Handle)
Definition: dllmain.c:3507
LONG NTSTATUS
Definition: precomp.h:26
HANDLE SockAsyncCompletionPort
Definition: dllmain.c:28
HWND hWnd
Definition: settings.c:17
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
INT WSPAPI WSPAsyncSelect(IN SOCKET Handle, IN HWND hWnd, IN UINT wMsg, IN LONG lEvent, OUT LPINT lpErrno)
Definition: sndrcv.c:17
ULONG AfdFlags
Definition: shared.h:87
DWORD SequenceNumber
Definition: msafd.h:90
PAFD_WSABUF BufferArray
Definition: shared.h:92
#define FD_READ
Definition: winsock.h:405
#define IOCTL_AFD_RECV_DATAGRAM
Definition: shared.h:279
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)
#define TDI_RECEIVE_EXPEDITED
Definition: tdi.h:123
VOID NTAPI AfdAPC(PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, ULONG Reserved)
Definition: sndrcv.c:140
BOOLEAN SockCreateOrReferenceAsyncThread(VOID)
Definition: dllmain.c:3580
int32_t INT
Definition: typedefs.h:56
#define FD_OOB
Definition: winsock.h:407
DWORD CreateFlags
Definition: msafd.h:81
#define FD_WRITE
Definition: winsock.h:406
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 AFD_SKIP_FIO
Definition: shared.h:218
#define TDI_RECEIVE_NORMAL
Definition: tdi.h:122
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
ULONG BufferCount
Definition: shared.h:109
VOID SockProcessQueuedAsyncSelect(PVOID Context, PIO_STATUS_BLOCK IoStatusBlock)
Definition: dllmain.c:3949
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define MSG_OOB
Definition: winsock.h:221
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
long LONG
Definition: pedump.c:60
#define EVENT_ALL_ACCESS
Definition: isotest.c:82
PSOCK_SHARED_INFO SharedData
Definition: msafd.h:100
INT MaxWSAddressLength
Definition: helpers.h:17
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define IOCTL_AFD_SEND_DATAGRAM
Definition: shared.h:283
_Reserved_ PVOID Reserved
Definition: winddi.h:3974
PHELPER_DATA HelperData
Definition: msafd.h:103
#define TDI_SEND_EXPEDITED
Definition: tdi.h:135
ULONG TdiFlags
Definition: shared.h:95
PAFD_WSABUF BufferArray
Definition: shared.h:108
#define AFD_INFO_BLOCKING_MODE
Definition: shared.h:183
ULONG AfdFlags
Definition: shared.h:103
ULONG BufferCount
Definition: shared.h:102
BOOLEAN NonBlocking
Definition: msafd.h:74
_In_ HANDLE Handle
Definition: extypes.h:390
#define AFD_OVERLAPPED
Definition: shared.h:219
DWORD ServiceFlags1
Definition: msafd.h:82
#define TRACE(s)
Definition: solgame.cpp:4
#define GetProcessHeap()
Definition: compat.h:395
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
#define INVALID_SOCKET
Definition: winsock.h:332
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
#define TDI_SEND_PARTIAL
Definition: tdi.h:136
unsigned long DWORD
Definition: ntddk_ex.h:95
FORCEINLINE DWORD MsafdReturnWithErrno(NTSTATUS Status, LPINT Errno, DWORD Received, LPDWORD ReturnedBytes)
Definition: msafd.h:546
#define STATUS_RECEIVE_EXPEDITED
Definition: ntstatus.h:130
struct _IO_STATUS_BLOCK * PIO_STATUS_BLOCK
Definition: change.c:34
PAFD_WSABUF BufferArray
Definition: shared.h:85
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
PSOCKET_INFORMATION ParentSocket
Definition: msafd.h:130
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
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
#define MSG_PARTIAL
Definition: winsock.h:402
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
ULONG TdiFlags
Definition: shared.h:88
ULONG BufferCount
Definition: shared.h:86
#define IOCTL_AFD_SEND
Definition: shared.h:281
HANDLE lEvent
Definition: tftpd.cpp:56
GLdouble s
Definition: gl.h:2039
#define IOCTL_AFD_RECV
Definition: shared.h:277
struct _AFD_WSABUF * PAFD_WSABUF
HANDLE GlobalHeap
Definition: dllmain.c:19
PAFD_WSABUF BufferArray
Definition: shared.h:101
#define SO_SYNCHRONOUS_NONALERT
Definition: ws2_32.h:41
INT WSPAPI WSPBind(SOCKET Handle, const struct sockaddr *SocketAddress, int SocketAddressLength, LPINT lpErrno)
Definition: dllmain.c:846
Status
Definition: gdiplustypes.h:24
u_short sa_family
Definition: winsock.h:217
#define ERR(fmt,...)
Definition: debug.h:109
_In_ HANDLE _In_ DWORD _In_ DWORD _Inout_opt_ LPOVERLAPPED lpOverlapped
Definition: mswsock.h:90
int SetSocketInformation(PSOCKET_INFORMATION Socket, ULONG AfdInformationClass, PBOOLEAN Boolean OPTIONAL, PULONG Ulong OPTIONAL, PLARGE_INTEGER LargeInteger OPTIONAL, LPWSAOVERLAPPED Overlapped OPTIONAL, LPWSAOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine OPTIONAL)
Definition: dllmain.c:3384
LONG AsyncDisabledEvents
Definition: msafd.h:93
#define XP1_CONNECTIONLESS
Definition: winsock2.h:436
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
unsigned int UINT
Definition: ndis.h:50
#define TDI_RECEIVE_PEEK
Definition: tdi.h:124
#define STATUS_RECEIVE_PARTIAL_EXPEDITED
Definition: ntstatus.h:131
ULONG BufferCount
Definition: shared.h:93
SOCKET_STATE State
Definition: msafd.h:54
#define OUT
Definition: typedefs.h:39
void(CALLBACK * LPWSAOVERLAPPED_COMPLETION_ROUTINE)(IN DWORD dwError, IN DWORD cbTransferred, IN LPWSAOVERLAPPED lpOverlapped, IN DWORD dwFlags)
Definition: winsock2.h:722
uint32_t * LPDWORD
Definition: typedefs.h:57
unsigned int ULONG
Definition: retypes.h:1
#define UNIMPLEMENTED
Definition: debug.h:114
INT MaxTDIAddressLength
Definition: helpers.h:19
UINT_PTR SOCKET
Definition: winsock.h:47
PVOID HelperContext
Definition: msafd.h:104
#define INFINITE
Definition: serial.h:102
return STATUS_SUCCESS
Definition: btrfs.c:2725
LONG AsyncEvents
Definition: msafd.h:92
#define HeapFree(x, y, z)
Definition: compat.h:394
_Must_inspect_result_ _In_ ULONG _In_ PSOCKADDR _In_ PSOCKADDR RemoteAddress
Definition: wsk.h:170
int * LPINT
Definition: windef.h:178
#define WSPAPI
Definition: ws2spi.h:39
#define MSG_PEEK
Definition: winsock.h:222