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