ReactOS 0.4.16-dev-2208-g6350669
sndrcv.c File Reference
#include <msafd.h>
Include dependency graph for sndrcv.c:

Go to the source code of this file.

Functions

INT WSPAPI WSPAsyncSelect (IN SOCKET Handle, IN HWND hWnd, IN UINT wMsg, IN LONG lEvent, OUT LPINT lpErrno)
 
BOOL WSPAPI WSPGetOverlappedResult (IN SOCKET Handle, IN LPWSAOVERLAPPED lpOverlapped, OUT LPDWORD lpdwBytes, IN BOOL fWait, OUT LPDWORD lpdwFlags, OUT LPINT lpErrno)
 
static VOID NTAPI MsafdRecvAPC (_In_ PVOID ApcContext, _In_ PIO_STATUS_BLOCK IoStatusBlock, _In_ ULONG Reserved)
 
static VOID NTAPI MsafdSendAPC (_In_ PVOID ApcContext, _In_ PIO_STATUS_BLOCK IoStatusBlock, _In_ ULONG Reserved)
 
int WSPAPI WSPRecv (SOCKET Handle, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesRead, LPDWORD ReceiveFlags, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, LPWSATHREADID lpThreadId, LPINT lpErrno)
 
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)
 
int WSPAPI WSPSend (SOCKET Handle, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesSent, DWORD iFlags, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, LPWSATHREADID lpThreadId, LPINT lpErrno)
 
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)
 
INT WSPAPI WSPRecvDisconnect (IN SOCKET s, OUT LPWSABUF lpInboundDisconnectData, OUT LPINT lpErrno)
 
INT WSPAPI WSPSendDisconnect (IN SOCKET s, IN LPWSABUF lpOutboundDisconnectData, OUT LPINT lpErrno)
 

Function Documentation

◆ MsafdRecvAPC()

static VOID NTAPI MsafdRecvAPC ( _In_ PVOID  ApcContext,
_In_ PIO_STATUS_BLOCK  IoStatusBlock,
_In_ ULONG  Reserved 
)
static

Definition at line 171 of file sndrcv.c.

175{
177
178 TRACE("MsafdRecvAPC(%p %lx %lx)\n", ApcContext, IoStatusBlock->Status, IoStatusBlock->Information);
179
180 /* Re-enable Async Event */
183 {
185 }
186 else
187 {
189 }
190
191 if (Context->lpCompletionRoutine)
193
195}
#define HeapFree(x, y, z)
Definition: compat.h:735
HANDLE GlobalHeap
Definition: dllmain.c:19
VOID SockReenableAsyncSelectEvent(IN PSOCKET_INFORMATION Socket, IN ULONG Event)
Definition: dllmain.c:4105
_In_opt_ HANDLE _In_opt_ PIO_APC_ROUTINE _In_opt_ PVOID ApcContext
Definition: iofuncs.h:727
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define STATUS_RECEIVE_EXPEDITED
Definition: ntstatus.h:205
#define STATUS_RECEIVE_PARTIAL_EXPEDITED
Definition: ntstatus.h:206
#define TRACE(s)
Definition: solgame.cpp:4
#define FD_READ
Definition: winsock.h:399
#define FD_OOB
Definition: winsock.h:401

Referenced by WSPRecv(), and WSPRecvFrom().

◆ MsafdSendAPC()

static VOID NTAPI MsafdSendAPC ( _In_ PVOID  ApcContext,
_In_ PIO_STATUS_BLOCK  IoStatusBlock,
_In_ ULONG  Reserved 
)
static

Definition at line 200 of file sndrcv.c.

204{
206
207 TRACE("MsafdSendAPC(%p %lx %lx)\n", ApcContext, IoStatusBlock->Status, IoStatusBlock->Information);
208
209 /* Re-enable Async Event */
211
212 if (Context->lpCompletionRoutine)
214
215 /* Free IOCTL buffers */
217}
#define FD_WRITE
Definition: winsock.h:400

Referenced by WSPSend(), and WSPSendTo().

◆ WSPAsyncSelect()

INT WSPAPI WSPAsyncSelect ( IN SOCKET  Handle,
IN HWND  hWnd,
IN UINT  wMsg,
IN LONG  lEvent,
OUT LPINT  lpErrno 
)

Definition at line 17 of file sndrcv.c.

22{
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;
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}
unsigned char BOOLEAN
HWND hWnd
Definition: settings.c:17
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define GetProcessHeap()
Definition: compat.h:736
#define HeapAlloc
Definition: compat.h:733
HANDLE SockAsyncCompletionPort
Definition: dllmain.c:28
BOOLEAN SockCreateOrReferenceAsyncThread(VOID)
Definition: dllmain.c:3702
PSOCKET_INFORMATION GetSocketStructure(SOCKET Handle)
Definition: dllmain.c:3629
VOID SockProcessQueuedAsyncSelect(PVOID Context, PIO_STATUS_BLOCK IoStatusBlock)
Definition: dllmain.c:4071
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:3507
BOOLEAN SockGetAsyncSelectHelperAfdHandle(VOID)
Definition: dllmain.c:3797
int WSPAPI WSPEventSelect(IN SOCKET Handle, IN WSAEVENT hEventObject, IN long lNetworkEvents, OUT LPINT lpErrno)
Definition: event.c:17
FORCEINLINE DWORD MsafdReturnWithErrno(_In_ NTSTATUS Status, _Out_opt_ LPINT Errno, _In_ DWORD Received, _Out_opt_ LPDWORD ReturnedBytes)
Definition: msafd.h:568
ULONG Handle
Definition: gdb_input.c:15
NTSTATUS NTAPI NtSetIoCompletion(IN HANDLE IoCompletionPortHandle, IN PVOID CompletionKey, IN PVOID CompletionContext, IN NTSTATUS CompletionStatus, IN ULONG CompletionInformation)
Definition: iocomp.c:569
#define AFD_INFO_BLOCKING_MODE
Definition: shared.h:183
DWORD SequenceNumber
Definition: msafd.h:131
PSOCKET_INFORMATION ParentSocket
Definition: msafd.h:130
PSOCK_SHARED_INFO SharedData
Definition: msafd.h:100
LONG AsyncDisabledEvents
Definition: msafd.h:93
BOOLEAN NonBlocking
Definition: msafd.h:74
LONG AsyncEvents
Definition: msafd.h:92
DWORD SequenceNumber
Definition: msafd.h:90
HANDLE lEvent
Definition: tftpd.cpp:56
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define WSAENOTSOCK
Definition: winerror.h:2854
#define INVALID_SOCKET
Definition: winsock.h:326
#define SOCKET_ERROR
Definition: winsock.h:327

Referenced by WSPStartup().

◆ WSPGetOverlappedResult()

BOOL WSPAPI WSPGetOverlappedResult ( IN SOCKET  Handle,
IN LPWSAOVERLAPPED  lpOverlapped,
OUT LPDWORD  lpdwBytes,
IN BOOL  fWait,
OUT LPDWORD  lpdwFlags,
OUT LPINT  lpErrno 
)

Definition at line 96 of file sndrcv.c.

103{
104 PSOCKET_INFORMATION Socket;
106 BOOL Ret;
107
108 TRACE("Called (%x)\n", Handle);
109
110 /* Get the Socket Structure associate to this Socket*/
111 Socket = GetSocketStructure(Handle);
112 if (!Socket)
113 {
114 if(lpErrno)
115 *lpErrno = WSAENOTSOCK;
116 return FALSE;
117 }
118 if (!lpOverlapped || !lpdwBytes || !lpdwFlags)
119 {
120 if (lpErrno)
121 *lpErrno = WSAEFAULT;
122 return FALSE;
123 }
124
126 Ret = GetOverlappedResult((HANDLE)Handle, lpOverlapped, lpdwBytes, fWait);
127
128 /* HACK: Allow APC to be processed */
129 SleepEx(0, TRUE);
130
131 if (!fWait && IoStatusBlock->Status == STATUS_PENDING)
132 {
133 if (lpErrno)
134 *lpErrno = WSA_IO_INCOMPLETE;
135 return FALSE;
136 }
137
138 if (Ret)
139 {
140
141 /* Re-enable Async Event */
145 }
146
147 switch (IoStatusBlock->Status)
148 {
150 *lpdwFlags = MSG_OOB;
151 break;
153 *lpdwFlags = MSG_PARTIAL | MSG_OOB;
154 break;
156 *lpdwFlags = MSG_PARTIAL;
157 break;
158 default:
159 *lpdwFlags = 0;
160 if (lpErrno)
162 break;
163 }
164
165 return Ret;
166}
#define FALSE
Definition: types.h:117
INT TranslateNtStatusError(NTSTATUS Status)
Definition: dllmain.c:537
struct _IO_STATUS_BLOCK * PIO_STATUS_BLOCK
Definition: change.c:34
unsigned int BOOL
Definition: ntddk_ex.h:94
BOOL WINAPI GetOverlappedResult(IN HANDLE hFile, IN LPOVERLAPPED lpOverlapped, OUT LPDWORD lpNumberOfBytesTransferred, IN BOOL bWait)
Definition: iocompl.c:221
_In_ HANDLE _In_ DWORD _In_ DWORD _Inout_opt_ LPOVERLAPPED lpOverlapped
Definition: mswsock.h:93
#define STATUS_RECEIVE_PARTIAL
Definition: ntstatus.h:204
DWORD WINAPI SleepEx(IN DWORD dwMilliseconds, IN BOOL bAlertable)
Definition: synch.c:802
#define STATUS_PENDING
Definition: telnetd.h:14
#define WSAEFAULT
Definition: winerror.h:2844
#define WSA_IO_INCOMPLETE
Definition: winsock2.h:611
#define MSG_OOB
Definition: winsock.h:215
#define MSG_PARTIAL
Definition: winsock.h:396

Referenced by WSPStartup().

◆ WSPRecv()

int WSPAPI WSPRecv ( SOCKET  Handle,
LPWSABUF  lpBuffers,
DWORD  dwBufferCount,
LPDWORD  lpNumberOfBytesRead,
LPDWORD  ReceiveFlags,
LPWSAOVERLAPPED  lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE  lpCompletionRoutine,
LPWSATHREADID  lpThreadId,
LPINT  lpErrno 
)

Definition at line 221 of file sndrcv.c.

230{
231 PIO_STATUS_BLOCK IOSB;
232 IO_STATUS_BLOCK DummyIOSB;
233 AFD_RECV_INFO RecvInfo;
235 PMSAFD_RECV_APC_CONTEXT APCContext;
236 PIO_APC_ROUTINE APCFunction = NULL;
237 HANDLE Event = NULL;
239 PSOCKET_INFORMATION Socket;
240 DWORD NumberOfBytesRead;
241
242 TRACE("WSPRecv(%x)\n", Handle);
243
244 /* Get the Socket Structure associate to this Socket*/
245 Socket = GetSocketStructure(Handle);
246 if (!Socket)
247 {
248 if (lpErrno)
249 *lpErrno = WSAENOTSOCK;
250 return SOCKET_ERROR;
251 }
252 if (!lpNumberOfBytesRead && !lpOverlapped)
253 {
254 if (lpErrno)
255 *lpErrno = WSAEFAULT;
256 return SOCKET_ERROR;
257 }
258 if (Socket->SharedData->OobInline && ReceiveFlags && (*ReceiveFlags & MSG_OOB) != 0)
259 {
260 if (lpErrno)
261 *lpErrno = WSAEINVAL;
262 return SOCKET_ERROR;
263 }
264
265 memset(&RecvInfo, 0, sizeof(RecvInfo));
266
269
270 if (!NT_SUCCESS(Status))
271 {
272 return SOCKET_ERROR;
273 }
274
275 /* Set up the Receive Structure */
276 RecvInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
277 RecvInfo.BufferCount = dwBufferCount;
278 RecvInfo.TdiFlags = 0;
279 RecvInfo.AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0;
280
281 /* Set the TDI Flags */
282 if (!ReceiveFlags || *ReceiveFlags == 0)
283 {
284 RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL;
285 }
286 else
287 {
288 if (*ReceiveFlags & MSG_OOB)
289 {
291 }
292
293 if (*ReceiveFlags & MSG_PEEK)
294 {
295 RecvInfo.TdiFlags |= TDI_RECEIVE_PEEK;
296 }
297
298 if (*ReceiveFlags & MSG_PARTIAL)
299 {
300 RecvInfo.TdiFlags |= TDI_RECEIVE_PARTIAL;
301 }
302 }
303
304 /* Verify if we should use APC */
305 if (!lpOverlapped)
306 {
307 /* Not using Overlapped structure, so use normal blocking on event */
308 APCContext = NULL;
309 APCFunction = NULL;
311 IOSB = &DummyIOSB;
312 }
313 else
314 {
315 /* Overlapped request for non overlapped opened socket */
316 if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0)
317 {
318 TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
320 return MsafdReturnWithErrno(STATUS_SUCCESS, lpErrno, 0, lpNumberOfBytesRead);
321 }
322
324 if (lpCompletionRoutine)
325 {
326 RecvInfo.AfdFlags |= AFD_SKIP_FIO;
327 APCFunction = &MsafdRecvAPC;
328 APCContext = HeapAlloc(GlobalHeap, 0, sizeof(*APCContext));
329 if (!APCContext)
330 {
331 ERR("Not enough memory for APC Context\n");
333 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, lpNumberOfBytesRead);
334 }
335 APCContext->lpCompletionRoutine = lpCompletionRoutine;
336 APCContext->lpOverlapped = lpOverlapped;
337 APCContext->lpSocket = Socket;
338 Event = NULL;
339 }
340 else
341 {
342 // .NET expects APCContext to be a pointer to lpOverlapped, because it adds some additional metadata past OVERLAPPED structure
343 // Do not use APC when there is no completion context
344 Event = lpOverlapped->hEvent;
345
346 APCFunction = NULL;
347 if (Event)
348 {
349 APCContext = NULL;
350 }
351 else
352 {
354 }
355 }
356
357 RecvInfo.AfdFlags |= AFD_OVERLAPPED;
358 }
359
360 IOSB->Information = 0;
361 IOSB->Status = STATUS_PENDING;
362
363 /* Send IOCTL */
365 Event,
366 APCFunction,
367 APCContext,
368 IOSB,
370 &RecvInfo,
371 sizeof(RecvInfo),
372 NULL,
373 0);
374
375 /* Wait for completion if not overlapped */
377 {
378 /* It's up to the protocol to time out recv. We must wait
379 * until the protocol decides it's had enough. */
381 Status = IOSB->Status;
382 }
383
385
386 if (Status == STATUS_PENDING)
387 {
388 TRACE("Leaving (Pending)\n");
389 return MsafdReturnWithErrno(Status, lpErrno, 0, NULL);
390 }
391
392 NumberOfBytesRead = (DWORD)IOSB->Information;
393
394 /* Return the Flags */
395 if (ReceiveFlags)
396 {
397 switch (Status)
398 {
400 *ReceiveFlags = MSG_OOB;
401 break;
403 *ReceiveFlags = MSG_PARTIAL | MSG_OOB;
404 break;
406 *ReceiveFlags = MSG_PARTIAL;
407 break;
408 default:
409 *ReceiveFlags = 0;
410 break;
411 }
412 }
413
414 /* Re-enable Async Event */
415 if (ReceiveFlags && (*ReceiveFlags & MSG_OOB))
416 {
418 }
419 else
420 {
422 }
423
424 TRACE("Leaving (%lx %ld)\n", Status, NumberOfBytesRead);
425 return MsafdReturnWithErrno(Status, lpErrno, NumberOfBytesRead, lpNumberOfBytesRead);
426}
LONG NTSTATUS
Definition: precomp.h:26
#define ERR(fmt,...)
Definition: precomp.h:57
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
VOID MsafdWaitForAlert(_In_ HANDLE hObject)
Definition: dllmain.c:614
struct _MSAFD_RECV_APC_CONTEXT * PMSAFD_RECV_APC_CONTEXT
HANDLE SockEvent
#define SO_SYNCHRONOUS_NONALERT
Definition: ws2_32.h:41
unsigned long DWORD
Definition: ntddk_ex.h:95
Status
Definition: gdiplustypes.h:25
#define EVENT_ALL_ACCESS
Definition: isotest.c:82
if(dx< 0)
Definition: linetemp.h:194
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)
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
#define DWORD
Definition: nt_native.h:44
VOID(* PIO_APC_ROUTINE)(IN PVOID ApcContext, IN PIO_STATUS_BLOCK IoStatusBlock, IN ULONG Reserved)
Definition: nt_native.h:880
@ SynchronizationEvent
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:96
#define AFD_IMMEDIATE
Definition: shared.h:220
#define AFD_OVERLAPPED
Definition: shared.h:219
#define IOCTL_AFD_RECV
Definition: shared.h:277
#define AFD_SKIP_FIO
Definition: shared.h:218
struct _AFD_WSABUF * PAFD_WSABUF
#define memset(x, y, z)
Definition: compat.h:39
#define STATUS_SUCCESS
Definition: shellext.h:65
static VOID NTAPI MsafdRecvAPC(_In_ PVOID ApcContext, _In_ PIO_STATUS_BLOCK IoStatusBlock, _In_ ULONG Reserved)
Definition: sndrcv.c:171
ULONG BufferCount
Definition: shared.h:86
ULONG TdiFlags
Definition: shared.h:88
ULONG AfdFlags
Definition: shared.h:87
PAFD_WSABUF BufferArray
Definition: shared.h:85
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
Definition: msafd.h:154
LPWSAOVERLAPPED lpOverlapped
Definition: msafd.h:153
PSOCKET_INFORMATION lpSocket
Definition: msafd.h:155
BOOLEAN OobInline
Definition: msafd.h:71
DWORD CreateFlags
Definition: msafd.h:81
#define TDI_RECEIVE_PARTIAL
Definition: tdi.h:121
#define TDI_RECEIVE_EXPEDITED
Definition: tdi.h:123
#define TDI_RECEIVE_PEEK
Definition: tdi.h:124
#define TDI_RECEIVE_NORMAL
Definition: tdi.h:122
#define WSAEINVAL
Definition: winerror.h:2845
#define MSG_PEEK
Definition: winsock.h:216

Referenced by WSPRecvFrom(), and WSPStartup().

◆ WSPRecvDisconnect()

INT WSPAPI WSPRecvDisconnect ( IN SOCKET  s,
OUT LPWSABUF  lpInboundDisconnectData,
OUT LPINT  lpErrno 
)

Definition at line 1052 of file sndrcv.c.

1055{
1057 return 0;
1058}
#define UNIMPLEMENTED
Definition: ntoskrnl.c:15

Referenced by WSPStartup().

◆ WSPRecvFrom()

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 at line 430 of file sndrcv.c.

441{
442 PIO_STATUS_BLOCK IOSB;
443 IO_STATUS_BLOCK DummyIOSB;
444 AFD_RECV_INFO_UDP RecvInfo;
446 PMSAFD_RECV_APC_CONTEXT APCContext;
447 PIO_APC_ROUTINE APCFunction = NULL;
448 HANDLE Event = NULL;
450 PSOCKET_INFORMATION Socket;
451 DWORD NumberOfBytesRead;
452
453 TRACE("WSPRecvFrom(%x)\n", Handle);
454
455 /* Get the Socket Structure associate to this Socket*/
456 Socket = GetSocketStructure(Handle);
457 if (!Socket)
458 {
459 if (lpErrno)
460 *lpErrno = WSAENOTSOCK;
461 return SOCKET_ERROR;
462 }
463 if (!lpNumberOfBytesRead && !lpOverlapped)
464 {
465 if (lpErrno)
466 *lpErrno = WSAEFAULT;
467 return SOCKET_ERROR;
468 }
469 if (Socket->SharedData->OobInline && ReceiveFlags && (*ReceiveFlags & MSG_OOB) != 0)
470 {
471 if (lpErrno)
472 *lpErrno = WSAEINVAL;
473 return SOCKET_ERROR;
474 }
475
477 {
478 /* Call WSPRecv for a non-datagram socket */
479 return WSPRecv(Handle,
480 lpBuffers,
481 dwBufferCount,
482 lpNumberOfBytesRead,
483 ReceiveFlags,
485 lpCompletionRoutine,
486 lpThreadId,
487 lpErrno);
488 }
489
490 /* Bind us First */
491 if (Socket->SharedData->State == SocketOpen)
492 {
494 SocketAddress,
495 SocketAddressLength);
496 /* Bind it */
497 if (WSPBind(Handle, SocketAddress, *SocketAddressLength, lpErrno) == SOCKET_ERROR)
498 return SOCKET_ERROR;
499 }
500 memset(&RecvInfo, 0, sizeof(RecvInfo));
501
504
505 if( !NT_SUCCESS(Status) )
506 {
507 return SOCKET_ERROR;
508 }
509
510 /* Set up the Receive Structure */
511 RecvInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
512 RecvInfo.BufferCount = dwBufferCount;
513 RecvInfo.TdiFlags = 0;
514 RecvInfo.AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0;
515 RecvInfo.AddressLength = SocketAddressLength;
516 RecvInfo.Address = SocketAddress;
517
518 /* Set the TDI Flags */
519 if (!ReceiveFlags || *ReceiveFlags == 0)
520 {
521 RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL;
522 }
523 else
524 {
525 if (*ReceiveFlags & MSG_OOB)
526 {
528 }
529
530 if (*ReceiveFlags & MSG_PEEK)
531 {
532 RecvInfo.TdiFlags |= TDI_RECEIVE_PEEK;
533 }
534
535 if (*ReceiveFlags & MSG_PARTIAL)
536 {
537 RecvInfo.TdiFlags |= TDI_RECEIVE_PARTIAL;
538 }
539 }
540
541 /* Verify if we should use APC */
542 if (!lpOverlapped)
543 {
544 /* Not using Overlapped structure, so use normal blocking on event */
545 APCContext = NULL;
546 APCFunction = NULL;
548 IOSB = &DummyIOSB;
549 }
550 else
551 {
552 /* Overlapped request for non overlapped opened socket */
553 if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0)
554 {
555 TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
557 return MsafdReturnWithErrno(STATUS_SUCCESS, lpErrno, 0, lpNumberOfBytesRead);
558 }
559
561 if (lpCompletionRoutine)
562 {
563 RecvInfo.AfdFlags |= AFD_SKIP_FIO;
564 APCFunction = &MsafdRecvAPC;
565 APCContext = HeapAlloc(GlobalHeap, 0, sizeof(*APCContext));
566 if (!APCContext)
567 {
568 ERR("Not enough memory for APC Context\n");
570 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, lpNumberOfBytesRead);
571 }
572 APCContext->lpCompletionRoutine = lpCompletionRoutine;
573 APCContext->lpOverlapped = lpOverlapped;
574 APCContext->lpSocket = Socket;
575 Event = NULL;
576 }
577 else
578 {
579 // .NET expects APCContext to be a pointer to lpOverlapped, because it adds some additional metadata past OVERLAPPED structure
580 // Do not use APC when there is no completion context
581 Event = lpOverlapped->hEvent;
582
583 APCFunction = NULL;
584 if (Event)
585 {
586 APCContext = NULL;
587 }
588 else
589 {
591 }
592 }
593
594 RecvInfo.AfdFlags |= AFD_OVERLAPPED;
595 }
596
597 IOSB->Information = 0;
598 IOSB->Status = STATUS_PENDING;
599
600 /* Send IOCTL */
602 Event,
603 APCFunction,
604 APCContext,
605 IOSB,
607 &RecvInfo,
608 sizeof(RecvInfo),
609 NULL,
610 0);
611
612 /* Wait for completion if not overlapped */
614 {
615 /* FIXME: Shouldn't wait infinitely for receive... */
617 Status = IOSB->Status;
618 }
619
620 /* Return the Flags */
621 if (ReceiveFlags)
622 {
623 switch (Status)
624 {
626 *ReceiveFlags = MSG_OOB;
627 break;
629 *ReceiveFlags = MSG_PARTIAL | MSG_OOB;
630 break;
632 *ReceiveFlags = MSG_PARTIAL;
633 break;
634 default:
635 *ReceiveFlags = 0;
636 break;
637 }
638 }
639
641
642 if (Status == STATUS_PENDING)
643 {
644 TRACE("Leaving (Pending)\n");
645 *lpErrno = WSA_IO_PENDING;
646 return MsafdReturnWithErrno(Status, lpErrno, 0, NULL);
647 }
648
649 NumberOfBytesRead = (DWORD)IOSB->Information;
650
651 /* Re-enable Async Event */
652 if (ReceiveFlags && (*ReceiveFlags & MSG_OOB))
653 {
655 }
656 else
657 {
659 }
660
661 TRACE("Leaving (%lx %ld)\n", Status, NumberOfBytesRead);
662 return MsafdReturnWithErrno(Status, lpErrno, NumberOfBytesRead, lpNumberOfBytesRead);
663}
INT WSPAPI WSPBind(SOCKET Handle, const struct sockaddr *SocketAddress, int SocketAddressLength, LPINT lpErrno)
Definition: dllmain.c:860
@ SocketOpen
Definition: msafd.h:46
#define IOCTL_AFD_RECV_DATAGRAM
Definition: shared.h:279
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:221
ULONG AfdFlags
Definition: shared.h:94
PINT AddressLength
Definition: shared.h:97
ULONG BufferCount
Definition: shared.h:93
ULONG TdiFlags
Definition: shared.h:95
PAFD_WSABUF BufferArray
Definition: shared.h:92
PWSH_GET_WILDCARD_SOCKADDR WSHGetWildcardSockaddr
Definition: helpers.h:29
PVOID HelperContext
Definition: msafd.h:104
PHELPER_DATA HelperData
Definition: msafd.h:103
SOCKET_STATE State
Definition: msafd.h:54
DWORD ServiceFlags1
Definition: msafd.h:82
#define XP1_CONNECTIONLESS
Definition: winsock2.h:430
#define WSA_IO_PENDING
Definition: winsock2.h:610

Referenced by WSPStartup().

◆ WSPSend()

int WSPAPI WSPSend ( SOCKET  Handle,
LPWSABUF  lpBuffers,
DWORD  dwBufferCount,
LPDWORD  lpNumberOfBytesSent,
DWORD  iFlags,
LPWSAOVERLAPPED  lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE  lpCompletionRoutine,
LPWSATHREADID  lpThreadId,
LPINT  lpErrno 
)

Definition at line 668 of file sndrcv.c.

677{
678 PIO_STATUS_BLOCK IOSB;
679 IO_STATUS_BLOCK DummyIOSB;
680 AFD_SEND_INFO SendInfo;
682 PMSAFD_SEND_APC_CONTEXT APCContext;
683 PIO_APC_ROUTINE APCFunction = NULL;
684 HANDLE Event = NULL;
686 PSOCKET_INFORMATION Socket;
687 DWORD NumberOfBytesSent;
688
689 TRACE("WSPSend(%x)\n", Handle);
690
691 /* Get the Socket Structure associate to this Socket*/
692 Socket = GetSocketStructure(Handle);
693 if (!Socket)
694 {
695 if (lpErrno)
696 *lpErrno = WSAENOTSOCK;
697 return SOCKET_ERROR;
698 }
699 if (!lpNumberOfBytesSent && !lpOverlapped)
700 {
701 if (lpErrno)
702 *lpErrno = WSAEFAULT;
703 return SOCKET_ERROR;
704 }
705
706 memset(&SendInfo, 0, sizeof(SendInfo));
707
710
711 if( !NT_SUCCESS(Status) )
712 {
713 return SOCKET_ERROR;
714 }
715
716 /* Set up the Send Structure */
717 SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
718 SendInfo.BufferCount = dwBufferCount;
719 SendInfo.TdiFlags = 0;
720 SendInfo.AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0;
721
722 /* Set the TDI Flags */
723 if (iFlags)
724 {
725 if (iFlags & MSG_OOB)
726 {
727 SendInfo.TdiFlags |= TDI_SEND_EXPEDITED;
728 }
729 if (iFlags & MSG_PARTIAL)
730 {
731 SendInfo.TdiFlags |= TDI_SEND_PARTIAL;
732 }
733 }
734
735 /* Verify if we should use APC */
736 if (!lpOverlapped)
737 {
738 /* Not using Overlapped structure, so use normal blocking on event */
739 APCContext = NULL;
740 APCFunction = NULL;
742 IOSB = &DummyIOSB;
743 }
744 else
745 {
746 /* Overlapped request for non overlapped opened socket */
747 if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0)
748 {
749 TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
751 return MsafdReturnWithErrno(STATUS_SUCCESS, lpErrno, 0, lpNumberOfBytesSent);
752 }
753
755 if (lpCompletionRoutine)
756 {
757 SendInfo.AfdFlags |= AFD_SKIP_FIO;
758 APCFunction = &MsafdSendAPC;
759 APCContext = HeapAlloc(GlobalHeap, 0, sizeof(*APCContext));
760 if (!APCContext)
761 {
762 ERR("Not enough memory for APC Context\n");
764 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, lpNumberOfBytesSent);
765 }
766 APCContext->lpCompletionRoutine = lpCompletionRoutine;
767 APCContext->lpOverlapped = lpOverlapped;
768 APCContext->lpSocket = Socket;
769 APCContext->lpRemoteAddress = NULL;
770 Event = NULL;
771 }
772 else
773 {
774 // .NET expects APCContext to be a pointer to lpOverlapped, because it adds some additional metadata past OVERLAPPED structure
775 // Do not use APC when there is no completion context
776 Event = lpOverlapped->hEvent;
777
778 APCFunction = NULL;
779 if (Event)
780 {
781 APCContext = NULL;
782 }
783 else
784 {
786 }
787 }
788
789 Event = lpOverlapped->hEvent;
790 // APCContext is unsupported when using event
791 if (Event)
792 {
793 if (lpCompletionRoutine)
794 HeapFree(GetProcessHeap(), 0, APCContext);
795 APCContext = NULL;
796 }
797
798 SendInfo.AfdFlags |= AFD_OVERLAPPED;
799 }
800
801 IOSB->Information = 0;
802 IOSB->Status = STATUS_PENDING;
803
804 /* Send IOCTL */
806 Event,
807 APCFunction,
808 APCContext,
809 IOSB,
811 &SendInfo,
812 sizeof(SendInfo),
813 NULL,
814 0);
815
816 /* Wait for completion if not overlapped */
818 {
819 /* FIXME: Shouldn't wait infinitely for send... */
821 Status = IOSB->Status;
822 }
823
825
826 if (Status == STATUS_PENDING)
827 {
828 TRACE("Leaving (Pending)\n");
829 return MsafdReturnWithErrno(Status, lpErrno, 0, NULL);
830 }
831
832 NumberOfBytesSent = (DWORD)IOSB->Information;
833
834 /* Re-enable Async Event */
836
837 TRACE("Leaving (%lx %ld)\n", Status, NumberOfBytesSent);
838 return MsafdReturnWithErrno(Status, lpErrno, NumberOfBytesSent, lpNumberOfBytesSent);
839}
struct _MSAFD_SEND_APC_CONTEXT * PMSAFD_SEND_APC_CONTEXT
#define IOCTL_AFD_SEND
Definition: shared.h:281
static VOID NTAPI MsafdSendAPC(_In_ PVOID ApcContext, _In_ PIO_STATUS_BLOCK IoStatusBlock, _In_ ULONG Reserved)
Definition: sndrcv.c:200
ULONG BufferCount
Definition: shared.h:102
PAFD_WSABUF BufferArray
Definition: shared.h:101
ULONG TdiFlags
Definition: shared.h:104
ULONG AfdFlags
Definition: shared.h:103
LPWSAOVERLAPPED lpOverlapped
Definition: msafd.h:145
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
Definition: msafd.h:146
PSOCKET_INFORMATION lpSocket
Definition: msafd.h:147
PTRANSPORT_ADDRESS lpRemoteAddress
Definition: msafd.h:148
#define TDI_SEND_EXPEDITED
Definition: tdi.h:135
#define TDI_SEND_PARTIAL
Definition: tdi.h:136

Referenced by WSPSendTo(), and WSPStartup().

◆ WSPSendDisconnect()

INT WSPAPI WSPSendDisconnect ( IN SOCKET  s,
IN LPWSABUF  lpOutboundDisconnectData,
OUT LPINT  lpErrno 
)

Definition at line 1064 of file sndrcv.c.

1067{
1069 return 0;
1070}

Referenced by WSPStartup().

◆ WSPSendTo()

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 at line 843 of file sndrcv.c.

854{
855 PIO_STATUS_BLOCK IOSB;
856 IO_STATUS_BLOCK DummyIOSB;
857 AFD_SEND_INFO_UDP SendInfo;
859 PMSAFD_SEND_APC_CONTEXT APCContext;
860 PIO_APC_ROUTINE APCFunction = NULL;
861 HANDLE Event = NULL;
864 PSOCKET_INFORMATION Socket;
865 DWORD NumberOfBytesSent;
866 UCHAR Buffer[128];
867
868 TRACE("WSPSendTo(%x)\n", Handle);
869
870 /* Get the Socket Structure associate to this Socket */
871 Socket = GetSocketStructure(Handle);
872 if (!Socket)
873 {
874 if (lpErrno)
875 *lpErrno = WSAENOTSOCK;
876 return SOCKET_ERROR;
877 }
878 if (!lpNumberOfBytesSent && !lpOverlapped)
879 {
880 if (lpErrno)
881 *lpErrno = WSAEFAULT;
882 return SOCKET_ERROR;
883 }
884
886 {
887 /* Use WSPSend for connection-oriented sockets */
888 return WSPSend(Handle,
889 lpBuffers,
890 dwBufferCount,
891 lpNumberOfBytesSent,
892 iFlags,
894 lpCompletionRoutine,
895 lpThreadId,
896 lpErrno);
897 }
898
899 /* Bind us First */
900 if (Socket->SharedData->State == SocketOpen)
901 {
902 INT BindAddressLength;
903 PSOCKADDR BindAddress;
904 INT BindError;
905
906 /* Get the Wildcard Address */
907 BindAddressLength = Socket->HelperData->MaxWSAddressLength;
908 BindAddress = HeapAlloc(GlobalHeap, 0, BindAddressLength);
909 if (!BindAddress)
910 {
912 return INVALID_SOCKET;
913 }
914
916 BindAddress,
917 &BindAddressLength);
918 /* Bind it */
919 BindError = WSPBind(Handle, BindAddress, BindAddressLength, lpErrno);
920 HeapFree(GlobalHeap, 0, BindAddress);
921 if (BindError == SOCKET_ERROR)
922 return SOCKET_ERROR;
923 }
924
928
929 if (!NT_SUCCESS(Status))
930 {
931 return SOCKET_ERROR;
932 }
933
935
936 if (SocketAddressLength > 128 - sizeof(TRANSPORT_ADDRESS)) {
937 *lpErrno = WSAEFAULT;
938 return SOCKET_ERROR;
939 }
940
941 /* Fill TDI address */
942 RemoteAddress->TAAddressCount = 1;
943 RemoteAddress->Address[0].AddressLength = SocketAddressLength - sizeof(SocketAddress->sa_family);
944 RtlCopyMemory(&RemoteAddress->Address[0].AddressType, SocketAddress, SocketAddressLength);
945
946 /* Set up Structure */
947 SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
948 SendInfo.AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0;
949 SendInfo.BufferCount = dwBufferCount;
952
953 /* Verify if we should use APC */
954 if (!lpOverlapped)
955 {
956 /* Not using Overlapped structure, so use normal blocking on event */
957 APCContext = NULL;
958 APCFunction = NULL;
960 IOSB = &DummyIOSB;
961 }
962 else
963 {
964 /* Overlapped request for non overlapped opened socket */
965 if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0)
966 {
967 TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
969 return MsafdReturnWithErrno(STATUS_SUCCESS, lpErrno, 0, lpNumberOfBytesSent);
970 }
971
973 if (lpCompletionRoutine)
974 {
975 SendInfo.AfdFlags |= AFD_SKIP_FIO;
976 APCFunction = &MsafdSendAPC;
977 APCContext = HeapAlloc(GlobalHeap, 0, sizeof(*APCContext));
978 if (!APCContext)
979 {
980 ERR("Not enough memory for APC Context\n");
982 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, lpNumberOfBytesSent);
983 }
984 APCContext->lpCompletionRoutine = lpCompletionRoutine;
985 APCContext->lpOverlapped = lpOverlapped;
986 APCContext->lpSocket = Socket;
987 APCContext->lpRemoteAddress = RemoteAddress;
988 Event = NULL;
989 }
990 else
991 {
992 // .NET expects APCContext to be a pointer to lpOverlapped, because it adds some additional metadata past OVERLAPPED structure
993 // Do not use APC when there is no completion context
994 Event = lpOverlapped->hEvent;
995
996 APCFunction = NULL;
997 if (Event)
998 {
999 APCContext = NULL;
1000 }
1001 else
1002 {
1004 }
1005 }
1006
1007 SendInfo.AfdFlags |= AFD_OVERLAPPED;
1008 }
1009
1010 IOSB->Information = 0;
1011 IOSB->Status = STATUS_PENDING;
1012
1013 /* Send IOCTL */
1015 Event,
1016 APCFunction,
1017 APCContext,
1018 IOSB,
1020 &SendInfo,
1021 sizeof(SendInfo),
1022 NULL,
1023 0);
1024
1025 /* Wait for completion if not overlapped */
1027 {
1028 /* FIXME: Shouldn't wait infinitely for send... */
1030 Status = IOSB->Status;
1031 }
1032
1034
1035 if (Status == STATUS_PENDING)
1036 {
1037 TRACE("Leaving (Pending)\n");
1038 return MsafdReturnWithErrno(Status, lpErrno, 0, NULL);
1039 }
1040
1041 NumberOfBytesSent = (DWORD)IOSB->Information;
1042
1043 /* Re-enable Async Event */
1045
1046 TRACE("Leaving (%lx %ld)\n", Status, NumberOfBytesSent);
1047 return MsafdReturnWithErrno(Status, lpErrno, NumberOfBytesSent, lpNumberOfBytesSent);
1048}
Definition: bufpool.h:45
#define IOCTL_AFD_SEND_DATAGRAM
Definition: shared.h:283
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:668
ULONG BufferCount
Definition: shared.h:109
TDI_CONNECTION_INFORMATION TdiConnection
Definition: shared.h:112
PAFD_WSABUF BufferArray
Definition: shared.h:108
INT MaxTDIAddressLength
Definition: helpers.h:19
INT MaxWSAddressLength
Definition: helpers.h:17
u_short sa_family
Definition: winsock.h:211
struct _TRANSPORT_ADDRESS * PTRANSPORT_ADDRESS
int32_t INT
Definition: typedefs.h:58
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
_Must_inspect_result_ _In_ ULONG _In_ PSOCKADDR _In_ PSOCKADDR RemoteAddress
Definition: wsk.h:172
unsigned char UCHAR
Definition: xmlstorage.h:181

Referenced by WSPStartup().