xref: /reactos/dll/win32/msafd/misc/sndrcv.c (revision bf5e3320)
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
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
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
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
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,
201*bf5e3320SThomas 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 
294c2c66affSColin Finck     /* Wait for completion of not overlapped */
295c2c66affSColin Finck     if (Status == STATUS_PENDING && lpOverlapped == NULL)
296c2c66affSColin Finck     {
297c2c66affSColin Finck         /* It's up to the protocol to time out recv.  We must wait
298c2c66affSColin Finck          * until the protocol decides it's had enough.
299c2c66affSColin Finck          */
300c2c66affSColin Finck         WaitForSingleObject(SockEvent, INFINITE);
301c2c66affSColin Finck         Status = IOSB->Status;
302c2c66affSColin Finck     }
303c2c66affSColin Finck 
304c2c66affSColin Finck     NtClose( SockEvent );
305c2c66affSColin Finck 
306c2c66affSColin Finck     TRACE("Status %x Information %d\n", Status, IOSB->Information);
307c2c66affSColin Finck 
308c2c66affSColin Finck     if (Status == STATUS_PENDING)
309c2c66affSColin Finck     {
310c2c66affSColin Finck         TRACE("Leaving (Pending)\n");
311c2c66affSColin Finck         return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesRead);
312c2c66affSColin Finck     }
313c2c66affSColin Finck 
314c2c66affSColin Finck     /* Return the Flags */
315c2c66affSColin Finck     *ReceiveFlags = 0;
316c2c66affSColin Finck 
317c2c66affSColin Finck     switch (Status)
318c2c66affSColin Finck     {
319c2c66affSColin Finck         case STATUS_RECEIVE_EXPEDITED:
320c2c66affSColin Finck             *ReceiveFlags = MSG_OOB;
321c2c66affSColin Finck             break;
322c2c66affSColin Finck         case STATUS_RECEIVE_PARTIAL_EXPEDITED:
323c2c66affSColin Finck             *ReceiveFlags = MSG_PARTIAL | MSG_OOB;
324c2c66affSColin Finck             break;
325c2c66affSColin Finck         case STATUS_RECEIVE_PARTIAL:
326c2c66affSColin Finck             *ReceiveFlags = MSG_PARTIAL;
327c2c66affSColin Finck             break;
328c2c66affSColin Finck     }
329c2c66affSColin Finck 
330c2c66affSColin Finck     /* Re-enable Async Event */
331c2c66affSColin Finck     if (*ReceiveFlags & MSG_OOB)
332c2c66affSColin Finck     {
333c2c66affSColin Finck         SockReenableAsyncSelectEvent(Socket, FD_OOB);
334c2c66affSColin Finck     }
335c2c66affSColin Finck     else
336c2c66affSColin Finck     {
337c2c66affSColin Finck         SockReenableAsyncSelectEvent(Socket, FD_READ);
338c2c66affSColin Finck     }
339c2c66affSColin Finck 
340c2c66affSColin Finck     if (Status == STATUS_SUCCESS && lpOverlapped && lpCompletionRoutine)
341c2c66affSColin Finck     {
342c2c66affSColin Finck         lpCompletionRoutine(Status, IOSB->Information, lpOverlapped, *ReceiveFlags);
343c2c66affSColin Finck         HeapFree(GlobalHeap, 0, (PVOID)APCContext);
344c2c66affSColin Finck     }
345c2c66affSColin Finck 
346c2c66affSColin Finck     return MsafdReturnWithErrno ( Status, lpErrno, IOSB->Information, lpNumberOfBytesRead );
347c2c66affSColin Finck }
348c2c66affSColin Finck 
349c2c66affSColin Finck int
350c2c66affSColin Finck WSPAPI
351c2c66affSColin Finck WSPRecvFrom(SOCKET Handle,
352c2c66affSColin Finck             LPWSABUF lpBuffers,
353c2c66affSColin Finck             DWORD dwBufferCount,
354c2c66affSColin Finck             LPDWORD lpNumberOfBytesRead,
355c2c66affSColin Finck             LPDWORD ReceiveFlags,
356c2c66affSColin Finck             struct sockaddr *SocketAddress,
357c2c66affSColin Finck             int *SocketAddressLength,
358c2c66affSColin Finck             LPWSAOVERLAPPED lpOverlapped,
359c2c66affSColin Finck             LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
360c2c66affSColin Finck             LPWSATHREADID lpThreadId,
361c2c66affSColin Finck             LPINT lpErrno )
362c2c66affSColin Finck {
363c2c66affSColin Finck     PIO_STATUS_BLOCK            IOSB;
364c2c66affSColin Finck     IO_STATUS_BLOCK             DummyIOSB;
365c2c66affSColin Finck     AFD_RECV_INFO_UDP           RecvInfo;
366c2c66affSColin Finck     NTSTATUS                    Status;
367c2c66affSColin Finck     PVOID                       APCContext;
368c2c66affSColin Finck     PVOID                       APCFunction;
369c2c66affSColin Finck     HANDLE                      Event = NULL;
370c2c66affSColin Finck     HANDLE                      SockEvent;
371c2c66affSColin Finck     PSOCKET_INFORMATION         Socket;
372c2c66affSColin Finck 
373c2c66affSColin Finck     /* Get the Socket Structure associate to this Socket*/
374c2c66affSColin Finck     Socket = GetSocketStructure(Handle);
375c2c66affSColin Finck     if (!Socket)
376c2c66affSColin Finck     {
377c2c66affSColin Finck         if (lpErrno)
378c2c66affSColin Finck             *lpErrno = WSAENOTSOCK;
379c2c66affSColin Finck         return SOCKET_ERROR;
380c2c66affSColin Finck     }
381c2c66affSColin Finck     if (!lpNumberOfBytesRead && !lpOverlapped)
382c2c66affSColin Finck     {
383c2c66affSColin Finck         if (lpErrno)
384c2c66affSColin Finck             *lpErrno = WSAEFAULT;
385c2c66affSColin Finck         return SOCKET_ERROR;
386c2c66affSColin Finck     }
387c2c66affSColin Finck     if (Socket->SharedData->OobInline && ReceiveFlags && (*ReceiveFlags & MSG_OOB) != 0)
388c2c66affSColin Finck     {
389c2c66affSColin Finck         if (lpErrno)
390c2c66affSColin Finck             *lpErrno = WSAEINVAL;
391c2c66affSColin Finck         return SOCKET_ERROR;
392c2c66affSColin Finck     }
393c2c66affSColin Finck 
394c2c66affSColin Finck     if (!(Socket->SharedData->ServiceFlags1 & XP1_CONNECTIONLESS))
395c2c66affSColin Finck     {
396c2c66affSColin Finck         /* Call WSPRecv for a non-datagram socket */
397c2c66affSColin Finck         return WSPRecv(Handle,
398c2c66affSColin Finck                        lpBuffers,
399c2c66affSColin Finck                        dwBufferCount,
400c2c66affSColin Finck                        lpNumberOfBytesRead,
401c2c66affSColin Finck                        ReceiveFlags,
402c2c66affSColin Finck                        lpOverlapped,
403c2c66affSColin Finck                        lpCompletionRoutine,
404c2c66affSColin Finck                        lpThreadId,
405c2c66affSColin Finck                        lpErrno);
406c2c66affSColin Finck     }
407c2c66affSColin Finck 
408c2c66affSColin Finck     /* Bind us First */
409c2c66affSColin Finck     if (Socket->SharedData->State == SocketOpen)
410c2c66affSColin Finck     {
411c2c66affSColin Finck         Socket->HelperData->WSHGetWildcardSockaddr(Socket->HelperContext,
412c2c66affSColin Finck             SocketAddress,
413c2c66affSColin Finck             SocketAddressLength);
414c2c66affSColin Finck         /* Bind it */
415c2c66affSColin Finck         if (WSPBind(Handle, SocketAddress, *SocketAddressLength, lpErrno) == SOCKET_ERROR)
416c2c66affSColin Finck             return SOCKET_ERROR;
417c2c66affSColin Finck     }
418c2c66affSColin Finck 
419c2c66affSColin Finck     Status = NtCreateEvent( &SockEvent, EVENT_ALL_ACCESS,
420*bf5e3320SThomas Faber                             NULL, SynchronizationEvent, FALSE );
421c2c66affSColin Finck 
422c2c66affSColin Finck     if( !NT_SUCCESS(Status) )
423c2c66affSColin Finck         return -1;
424c2c66affSColin Finck 
425c2c66affSColin Finck     /* Set up the Receive Structure */
426c2c66affSColin Finck     RecvInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
427c2c66affSColin Finck     RecvInfo.BufferCount = dwBufferCount;
428c2c66affSColin Finck     RecvInfo.TdiFlags = 0;
429c2c66affSColin Finck     RecvInfo.AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0;
430c2c66affSColin Finck     RecvInfo.AddressLength = SocketAddressLength;
431c2c66affSColin Finck     RecvInfo.Address = SocketAddress;
432c2c66affSColin Finck 
433c2c66affSColin Finck     /* Set the TDI Flags */
434c2c66affSColin Finck     if (*ReceiveFlags == 0)
435c2c66affSColin Finck     {
436c2c66affSColin Finck         RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL;
437c2c66affSColin Finck     }
438c2c66affSColin Finck     else
439c2c66affSColin Finck     {
440c2c66affSColin Finck         if (*ReceiveFlags & MSG_OOB)
441c2c66affSColin Finck         {
442c2c66affSColin Finck             RecvInfo.TdiFlags |= TDI_RECEIVE_EXPEDITED;
443c2c66affSColin Finck         }
444c2c66affSColin Finck 
445c2c66affSColin Finck         if (*ReceiveFlags & MSG_PEEK)
446c2c66affSColin Finck         {
447c2c66affSColin Finck             RecvInfo.TdiFlags |= TDI_RECEIVE_PEEK;
448c2c66affSColin Finck         }
449c2c66affSColin Finck 
450c2c66affSColin Finck         if (*ReceiveFlags & MSG_PARTIAL)
451c2c66affSColin Finck         {
452c2c66affSColin Finck             RecvInfo.TdiFlags |= TDI_RECEIVE_PARTIAL;
453c2c66affSColin Finck         }
454c2c66affSColin Finck     }
455c2c66affSColin Finck 
456c2c66affSColin Finck     /* Verify if we should use APC */
457c2c66affSColin Finck 
458c2c66affSColin Finck     if (lpOverlapped == NULL)
459c2c66affSColin Finck     {
460c2c66affSColin Finck         /* Not using Overlapped structure, so use normal blocking on event */
461c2c66affSColin Finck         APCContext = NULL;
462c2c66affSColin Finck         APCFunction = NULL;
463c2c66affSColin Finck         Event = SockEvent;
464c2c66affSColin Finck         IOSB = &DummyIOSB;
465c2c66affSColin Finck     }
466c2c66affSColin Finck     else
467c2c66affSColin Finck     {
468c2c66affSColin Finck         /* Overlapped request for non overlapped opened socket */
469c2c66affSColin Finck         if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0)
470c2c66affSColin Finck         {
471c2c66affSColin Finck             TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
472c2c66affSColin Finck             return MsafdReturnWithErrno(0, lpErrno, 0, lpNumberOfBytesRead);
473c2c66affSColin Finck         }
474c2c66affSColin Finck         if (lpCompletionRoutine == NULL)
475c2c66affSColin Finck         {
476c2c66affSColin Finck             /* Using Overlapped Structure, but no Completion Routine, so no need for APC */
477c2c66affSColin Finck             APCContext = lpOverlapped;
478c2c66affSColin Finck             APCFunction = NULL;
479c2c66affSColin Finck             Event = lpOverlapped->hEvent;
480c2c66affSColin Finck         }
481c2c66affSColin Finck         else
482c2c66affSColin Finck         {
483c2c66affSColin Finck             /* Using Overlapped Structure and a Completion Routine, so use an APC */
484c2c66affSColin Finck             APCFunction = &AfdAPC; // should be a private io completion function inside us
485c2c66affSColin Finck             APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT));
486c2c66affSColin Finck             if (!APCContext)
487c2c66affSColin Finck             {
488c2c66affSColin Finck                 ERR("Not enough memory for APC Context\n");
489c2c66affSColin Finck                 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, lpNumberOfBytesRead);
490c2c66affSColin Finck             }
491c2c66affSColin Finck             ((PAFDAPCCONTEXT)APCContext)->lpCompletionRoutine = lpCompletionRoutine;
492c2c66affSColin Finck             ((PAFDAPCCONTEXT)APCContext)->lpOverlapped = lpOverlapped;
493c2c66affSColin Finck             ((PAFDAPCCONTEXT)APCContext)->lpSocket = Socket;
494c2c66affSColin Finck             RecvInfo.AfdFlags |= AFD_SKIP_FIO;
495c2c66affSColin Finck         }
496c2c66affSColin Finck 
497c2c66affSColin Finck         IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal;
498c2c66affSColin Finck         RecvInfo.AfdFlags |= AFD_OVERLAPPED;
499c2c66affSColin Finck     }
500c2c66affSColin Finck 
501c2c66affSColin Finck     IOSB->Status = STATUS_PENDING;
502c2c66affSColin Finck 
503c2c66affSColin Finck     /* Send IOCTL */
504c2c66affSColin Finck     Status = NtDeviceIoControlFile((HANDLE)Handle,
505c2c66affSColin Finck                                     Event,
506c2c66affSColin Finck                                     APCFunction,
507c2c66affSColin Finck                                     APCContext,
508c2c66affSColin Finck                                     IOSB,
509c2c66affSColin Finck                                     IOCTL_AFD_RECV_DATAGRAM,
510c2c66affSColin Finck                                     &RecvInfo,
511c2c66affSColin Finck                                     sizeof(RecvInfo),
512c2c66affSColin Finck                                     NULL,
513c2c66affSColin Finck                                     0);
514c2c66affSColin Finck 
515c2c66affSColin Finck     /* Wait for completion of not overlapped */
516c2c66affSColin Finck     if (Status == STATUS_PENDING && lpOverlapped == NULL)
517c2c66affSColin Finck     {
518c2c66affSColin Finck         WaitForSingleObject(SockEvent, INFINITE); // BUGBUG, shouldn wait infinitely for receive...
519c2c66affSColin Finck         Status = IOSB->Status;
520c2c66affSColin Finck     }
521c2c66affSColin Finck 
522c2c66affSColin Finck     NtClose( SockEvent );
523c2c66affSColin Finck 
524c2c66affSColin Finck     if (Status == STATUS_PENDING)
525c2c66affSColin Finck     {
526c2c66affSColin Finck         TRACE("Leaving (Pending)\n");
527c2c66affSColin Finck         return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesRead);
528c2c66affSColin Finck     }
529c2c66affSColin Finck 
530c2c66affSColin Finck     /* Return the Flags */
531c2c66affSColin Finck     *ReceiveFlags = 0;
532c2c66affSColin Finck 
533c2c66affSColin Finck     switch (Status)
534c2c66affSColin Finck     {
535c2c66affSColin Finck         case STATUS_RECEIVE_EXPEDITED:
536c2c66affSColin Finck             *ReceiveFlags = MSG_OOB;
537c2c66affSColin Finck             break;
538c2c66affSColin Finck         case STATUS_RECEIVE_PARTIAL_EXPEDITED:
539c2c66affSColin Finck             *ReceiveFlags = MSG_PARTIAL | MSG_OOB;
540c2c66affSColin Finck             break;
541c2c66affSColin Finck         case STATUS_RECEIVE_PARTIAL:
542c2c66affSColin Finck             *ReceiveFlags = MSG_PARTIAL;
543c2c66affSColin Finck             break;
544c2c66affSColin Finck     }
545c2c66affSColin Finck 
546c2c66affSColin Finck     /* Re-enable Async Event */
547c2c66affSColin Finck     if (*ReceiveFlags & MSG_OOB)
548c2c66affSColin Finck     {
549c2c66affSColin Finck         SockReenableAsyncSelectEvent(Socket, FD_OOB);
550c2c66affSColin Finck     }
551c2c66affSColin Finck     else
552c2c66affSColin Finck     {
553c2c66affSColin Finck         SockReenableAsyncSelectEvent(Socket, FD_READ);
554c2c66affSColin Finck     }
555c2c66affSColin Finck 
556c2c66affSColin Finck     if (Status == STATUS_SUCCESS && lpOverlapped && lpCompletionRoutine)
557c2c66affSColin Finck     {
558c2c66affSColin Finck         lpCompletionRoutine(Status, IOSB->Information, lpOverlapped, *ReceiveFlags);
559c2c66affSColin Finck         HeapFree(GlobalHeap, 0, (PVOID)APCContext);
560c2c66affSColin Finck     }
561c2c66affSColin Finck 
562c2c66affSColin Finck     return MsafdReturnWithErrno ( Status, lpErrno, IOSB->Information, lpNumberOfBytesRead );
563c2c66affSColin Finck }
564c2c66affSColin Finck 
565c2c66affSColin Finck 
566c2c66affSColin Finck int
567c2c66affSColin Finck WSPAPI
568c2c66affSColin Finck WSPSend(SOCKET Handle,
569c2c66affSColin Finck         LPWSABUF lpBuffers,
570c2c66affSColin Finck         DWORD dwBufferCount,
571c2c66affSColin Finck         LPDWORD lpNumberOfBytesSent,
572c2c66affSColin Finck         DWORD iFlags,
573c2c66affSColin Finck         LPWSAOVERLAPPED lpOverlapped,
574c2c66affSColin Finck         LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
575c2c66affSColin Finck         LPWSATHREADID lpThreadId,
576c2c66affSColin Finck         LPINT lpErrno)
577c2c66affSColin Finck {
578c2c66affSColin Finck     PIO_STATUS_BLOCK        IOSB;
579c2c66affSColin Finck     IO_STATUS_BLOCK         DummyIOSB;
580c2c66affSColin Finck     AFD_SEND_INFO           SendInfo;
581c2c66affSColin Finck     NTSTATUS                Status;
582c2c66affSColin Finck     PVOID                   APCContext;
583c2c66affSColin Finck     PVOID                   APCFunction;
584c2c66affSColin Finck     HANDLE                  Event = NULL;
585c2c66affSColin Finck     HANDLE                  SockEvent;
586c2c66affSColin Finck     PSOCKET_INFORMATION     Socket;
587c2c66affSColin Finck 
588c2c66affSColin Finck     /* Get the Socket Structure associate to this Socket*/
589c2c66affSColin Finck     Socket = GetSocketStructure(Handle);
590c2c66affSColin Finck     if (!Socket)
591c2c66affSColin Finck     {
592c2c66affSColin Finck         if (lpErrno)
593c2c66affSColin Finck             *lpErrno = WSAENOTSOCK;
594c2c66affSColin Finck         return SOCKET_ERROR;
595c2c66affSColin Finck     }
596c2c66affSColin Finck     if (!lpNumberOfBytesSent && !lpOverlapped)
597c2c66affSColin Finck     {
598c2c66affSColin Finck         if (lpErrno)
599c2c66affSColin Finck             *lpErrno = WSAEFAULT;
600c2c66affSColin Finck         return SOCKET_ERROR;
601c2c66affSColin Finck     }
602c2c66affSColin Finck 
603c2c66affSColin Finck     Status = NtCreateEvent( &SockEvent, EVENT_ALL_ACCESS,
604*bf5e3320SThomas Faber                             NULL, SynchronizationEvent, FALSE );
605c2c66affSColin Finck 
606c2c66affSColin Finck     if( !NT_SUCCESS(Status) )
607c2c66affSColin Finck         return -1;
608c2c66affSColin Finck 
609c2c66affSColin Finck     TRACE("Called\n");
610c2c66affSColin Finck 
611c2c66affSColin Finck     /* Set up the Send Structure */
612c2c66affSColin Finck     SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
613c2c66affSColin Finck     SendInfo.BufferCount = dwBufferCount;
614c2c66affSColin Finck     SendInfo.TdiFlags = 0;
615c2c66affSColin Finck     SendInfo.AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0;
616c2c66affSColin Finck 
617c2c66affSColin Finck     /* Set the TDI Flags */
618c2c66affSColin Finck     if (iFlags)
619c2c66affSColin Finck     {
620c2c66affSColin Finck         if (iFlags & MSG_OOB)
621c2c66affSColin Finck         {
622c2c66affSColin Finck             SendInfo.TdiFlags |= TDI_SEND_EXPEDITED;
623c2c66affSColin Finck         }
624c2c66affSColin Finck         if (iFlags & MSG_PARTIAL)
625c2c66affSColin Finck         {
626c2c66affSColin Finck             SendInfo.TdiFlags |= TDI_SEND_PARTIAL;
627c2c66affSColin Finck         }
628c2c66affSColin Finck     }
629c2c66affSColin Finck 
630c2c66affSColin Finck     /* Verify if we should use APC */
631c2c66affSColin Finck     if (lpOverlapped == NULL)
632c2c66affSColin Finck     {
633c2c66affSColin Finck         /* Not using Overlapped structure, so use normal blocking on event */
634c2c66affSColin Finck         APCContext = NULL;
635c2c66affSColin Finck         APCFunction = NULL;
636c2c66affSColin Finck         Event = SockEvent;
637c2c66affSColin Finck         IOSB = &DummyIOSB;
638c2c66affSColin Finck     }
639c2c66affSColin Finck     else
640c2c66affSColin Finck     {
641c2c66affSColin Finck         /* Overlapped request for non overlapped opened socket */
642c2c66affSColin Finck         if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0)
643c2c66affSColin Finck         {
644c2c66affSColin Finck             TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
645c2c66affSColin Finck             return MsafdReturnWithErrno(0, lpErrno, 0, lpNumberOfBytesSent);
646c2c66affSColin Finck         }
647c2c66affSColin Finck         if (lpCompletionRoutine == NULL)
648c2c66affSColin Finck         {
649c2c66affSColin Finck             /* Using Overlapped Structure, but no Completion Routine, so no need for APC */
650c2c66affSColin Finck             APCContext = lpOverlapped;
651c2c66affSColin Finck             APCFunction = NULL;
652c2c66affSColin Finck             Event = lpOverlapped->hEvent;
653c2c66affSColin Finck         }
654c2c66affSColin Finck         else
655c2c66affSColin Finck         {
656c2c66affSColin Finck             /* Using Overlapped Structure and a Completion Routine, so use an APC */
657c2c66affSColin Finck             APCFunction = &AfdAPC; // should be a private io completion function inside us
658c2c66affSColin Finck             APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT));
659c2c66affSColin Finck             if (!APCContext)
660c2c66affSColin Finck             {
661c2c66affSColin Finck                 ERR("Not enough memory for APC Context\n");
662c2c66affSColin Finck                 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, lpNumberOfBytesSent);
663c2c66affSColin Finck             }
664c2c66affSColin Finck             ((PAFDAPCCONTEXT)APCContext)->lpCompletionRoutine = lpCompletionRoutine;
665c2c66affSColin Finck             ((PAFDAPCCONTEXT)APCContext)->lpOverlapped = lpOverlapped;
666c2c66affSColin Finck             ((PAFDAPCCONTEXT)APCContext)->lpSocket = Socket;
667c2c66affSColin Finck             SendInfo.AfdFlags |= AFD_SKIP_FIO;
668c2c66affSColin Finck         }
669c2c66affSColin Finck 
670c2c66affSColin Finck         IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal;
671c2c66affSColin Finck         SendInfo.AfdFlags |= AFD_OVERLAPPED;
672c2c66affSColin Finck     }
673c2c66affSColin Finck 
674c2c66affSColin Finck     IOSB->Status = STATUS_PENDING;
675c2c66affSColin Finck 
676c2c66affSColin Finck     /* Send IOCTL */
677c2c66affSColin Finck     Status = NtDeviceIoControlFile((HANDLE)Handle,
678c2c66affSColin Finck                                     Event,
679c2c66affSColin Finck                                     APCFunction,
680c2c66affSColin Finck                                     APCContext,
681c2c66affSColin Finck                                     IOSB,
682c2c66affSColin Finck                                     IOCTL_AFD_SEND,
683c2c66affSColin Finck                                     &SendInfo,
684c2c66affSColin Finck                                     sizeof(SendInfo),
685c2c66affSColin Finck                                     NULL,
686c2c66affSColin Finck                                     0);
687c2c66affSColin Finck 
688c2c66affSColin Finck     /* Wait for completion of not overlapped */
689c2c66affSColin Finck     if (Status == STATUS_PENDING && lpOverlapped == NULL)
690c2c66affSColin Finck     {
691c2c66affSColin Finck         WaitForSingleObject(SockEvent, INFINITE); // BUGBUG, shouldn wait infinitely for send...
692c2c66affSColin Finck         Status = IOSB->Status;
693c2c66affSColin Finck     }
694c2c66affSColin Finck 
695c2c66affSColin Finck     NtClose( SockEvent );
696c2c66affSColin Finck 
697c2c66affSColin Finck     if (Status == STATUS_PENDING)
698c2c66affSColin Finck     {
699c2c66affSColin Finck         TRACE("Leaving (Pending)\n");
700c2c66affSColin Finck         return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesSent);
701c2c66affSColin Finck     }
702c2c66affSColin Finck 
703c2c66affSColin Finck     /* Re-enable Async Event */
704c2c66affSColin Finck     SockReenableAsyncSelectEvent(Socket, FD_WRITE);
705c2c66affSColin Finck 
706c2c66affSColin Finck     TRACE("Leaving (Success, %d)\n", IOSB->Information);
707c2c66affSColin Finck 
708c2c66affSColin Finck     if (Status == STATUS_SUCCESS && lpOverlapped && lpCompletionRoutine)
709c2c66affSColin Finck     {
710c2c66affSColin Finck         lpCompletionRoutine(Status, IOSB->Information, lpOverlapped, 0);
711c2c66affSColin Finck         HeapFree(GlobalHeap, 0, (PVOID)APCContext);
712c2c66affSColin Finck     }
713c2c66affSColin Finck 
714c2c66affSColin Finck     return MsafdReturnWithErrno( Status, lpErrno, IOSB->Information, lpNumberOfBytesSent );
715c2c66affSColin Finck }
716c2c66affSColin Finck 
717c2c66affSColin Finck int
718c2c66affSColin Finck WSPAPI
719c2c66affSColin Finck WSPSendTo(SOCKET Handle,
720c2c66affSColin Finck           LPWSABUF lpBuffers,
721c2c66affSColin Finck           DWORD dwBufferCount,
722c2c66affSColin Finck           LPDWORD lpNumberOfBytesSent,
723c2c66affSColin Finck           DWORD iFlags,
724c2c66affSColin Finck           const struct sockaddr *SocketAddress,
725c2c66affSColin Finck           int SocketAddressLength,
726c2c66affSColin Finck           LPWSAOVERLAPPED lpOverlapped,
727c2c66affSColin Finck           LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
728c2c66affSColin Finck           LPWSATHREADID lpThreadId,
729c2c66affSColin Finck           LPINT lpErrno)
730c2c66affSColin Finck {
731c2c66affSColin Finck     PIO_STATUS_BLOCK        IOSB;
732c2c66affSColin Finck     IO_STATUS_BLOCK         DummyIOSB;
733c2c66affSColin Finck     AFD_SEND_INFO_UDP       SendInfo;
734c2c66affSColin Finck     NTSTATUS                Status;
735c2c66affSColin Finck     PVOID                   APCContext;
736c2c66affSColin Finck     PVOID                   APCFunction;
737c2c66affSColin Finck     HANDLE                  Event = NULL;
738c2c66affSColin Finck     PTRANSPORT_ADDRESS      RemoteAddress;
739c2c66affSColin Finck     PSOCKADDR               BindAddress = NULL;
740c2c66affSColin Finck     INT                     BindAddressLength;
741c2c66affSColin Finck     HANDLE                  SockEvent;
742c2c66affSColin Finck     PSOCKET_INFORMATION     Socket;
743c2c66affSColin Finck 
744c2c66affSColin Finck     /* Get the Socket Structure associate to this Socket */
745c2c66affSColin Finck     Socket = GetSocketStructure(Handle);
746c2c66affSColin Finck     if (!Socket)
747c2c66affSColin Finck     {
748c2c66affSColin Finck         if (lpErrno)
749c2c66affSColin Finck             *lpErrno = WSAENOTSOCK;
750c2c66affSColin Finck         return SOCKET_ERROR;
751c2c66affSColin Finck     }
752c2c66affSColin Finck     if (!lpNumberOfBytesSent && !lpOverlapped)
753c2c66affSColin Finck     {
754c2c66affSColin Finck         if (lpErrno)
755c2c66affSColin Finck             *lpErrno = WSAEFAULT;
756c2c66affSColin Finck         return SOCKET_ERROR;
757c2c66affSColin Finck     }
758c2c66affSColin Finck 
759c2c66affSColin Finck     if (!(Socket->SharedData->ServiceFlags1 & XP1_CONNECTIONLESS))
760c2c66affSColin Finck     {
761c2c66affSColin Finck         /* Use WSPSend for connection-oriented sockets */
762c2c66affSColin Finck         return WSPSend(Handle,
763c2c66affSColin Finck                        lpBuffers,
764c2c66affSColin Finck                        dwBufferCount,
765c2c66affSColin Finck                        lpNumberOfBytesSent,
766c2c66affSColin Finck                        iFlags,
767c2c66affSColin Finck                        lpOverlapped,
768c2c66affSColin Finck                        lpCompletionRoutine,
769c2c66affSColin Finck                        lpThreadId,
770c2c66affSColin Finck                        lpErrno);
771c2c66affSColin Finck     }
772c2c66affSColin Finck 
773c2c66affSColin Finck     /* Bind us First */
774c2c66affSColin Finck     if (Socket->SharedData->State == SocketOpen)
775c2c66affSColin Finck     {
776c2c66affSColin Finck         /* Get the Wildcard Address */
777c2c66affSColin Finck         BindAddressLength = Socket->HelperData->MaxWSAddressLength;
778c2c66affSColin Finck         BindAddress = HeapAlloc(GlobalHeap, 0, BindAddressLength);
779c2c66affSColin Finck         if (!BindAddress)
780c2c66affSColin Finck         {
781c2c66affSColin Finck             MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL);
782c2c66affSColin Finck             return INVALID_SOCKET;
783c2c66affSColin Finck         }
784c2c66affSColin Finck 
785c2c66affSColin Finck         Socket->HelperData->WSHGetWildcardSockaddr(Socket->HelperContext,
786c2c66affSColin Finck                                                    BindAddress,
787c2c66affSColin Finck                                                    &BindAddressLength);
788c2c66affSColin Finck         /* Bind it */
789c2c66affSColin Finck         if (WSPBind(Handle, BindAddress, BindAddressLength, lpErrno) == SOCKET_ERROR)
790c2c66affSColin Finck             return SOCKET_ERROR;
791c2c66affSColin Finck     }
792c2c66affSColin Finck 
793c2c66affSColin Finck     RemoteAddress = HeapAlloc(GlobalHeap, 0, 0x6 + SocketAddressLength);
794c2c66affSColin Finck     if (!RemoteAddress)
795c2c66affSColin Finck     {
796c2c66affSColin Finck         if (BindAddress != NULL)
797c2c66affSColin Finck         {
798c2c66affSColin Finck             HeapFree(GlobalHeap, 0, BindAddress);
799c2c66affSColin Finck         }
800c2c66affSColin Finck         return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL);
801c2c66affSColin Finck     }
802c2c66affSColin Finck 
803c2c66affSColin Finck     Status = NtCreateEvent(&SockEvent,
804c2c66affSColin Finck                            EVENT_ALL_ACCESS,
805*bf5e3320SThomas Faber                            NULL, SynchronizationEvent, FALSE);
806c2c66affSColin Finck 
807c2c66affSColin Finck     if (!NT_SUCCESS(Status))
808c2c66affSColin Finck     {
809c2c66affSColin Finck         HeapFree(GlobalHeap, 0, RemoteAddress);
810c2c66affSColin Finck         if (BindAddress != NULL)
811c2c66affSColin Finck         {
812c2c66affSColin Finck             HeapFree(GlobalHeap, 0, BindAddress);
813c2c66affSColin Finck         }
814c2c66affSColin Finck         return SOCKET_ERROR;
815c2c66affSColin Finck     }
816c2c66affSColin Finck 
817c2c66affSColin Finck     /* Set up Address in TDI Format */
818c2c66affSColin Finck     RemoteAddress->TAAddressCount = 1;
819c2c66affSColin Finck     RemoteAddress->Address[0].AddressLength = SocketAddressLength - sizeof(SocketAddress->sa_family);
820c2c66affSColin Finck     RtlCopyMemory(&RemoteAddress->Address[0].AddressType, SocketAddress, SocketAddressLength);
821c2c66affSColin Finck 
822c2c66affSColin Finck     /* Set up Structure */
823c2c66affSColin Finck     SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
824c2c66affSColin Finck     SendInfo.AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0;
825c2c66affSColin Finck     SendInfo.BufferCount = dwBufferCount;
826c2c66affSColin Finck     SendInfo.TdiConnection.RemoteAddress = RemoteAddress;
827c2c66affSColin Finck     SendInfo.TdiConnection.RemoteAddressLength = Socket->HelperData->MaxTDIAddressLength;
828c2c66affSColin Finck 
829c2c66affSColin Finck     /* Verify if we should use APC */
830c2c66affSColin Finck     if (lpOverlapped == NULL)
831c2c66affSColin Finck     {
832c2c66affSColin Finck         /* Not using Overlapped structure, so use normal blocking on event */
833c2c66affSColin Finck         APCContext = NULL;
834c2c66affSColin Finck         APCFunction = NULL;
835c2c66affSColin Finck         Event = SockEvent;
836c2c66affSColin Finck         IOSB = &DummyIOSB;
837c2c66affSColin Finck     }
838c2c66affSColin Finck     else
839c2c66affSColin Finck     {
840c2c66affSColin Finck         /* Overlapped request for non overlapped opened socket */
841c2c66affSColin Finck         if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0)
842c2c66affSColin Finck         {
843c2c66affSColin Finck             TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
844c2c66affSColin Finck             return MsafdReturnWithErrno(0, lpErrno, 0, lpNumberOfBytesSent);
845c2c66affSColin Finck         }
846c2c66affSColin Finck         if (lpCompletionRoutine == NULL)
847c2c66affSColin Finck         {
848c2c66affSColin Finck             /* Using Overlapped Structure, but no Completion Routine, so no need for APC */
849c2c66affSColin Finck             APCContext = lpOverlapped;
850c2c66affSColin Finck             APCFunction = NULL;
851c2c66affSColin Finck             Event = lpOverlapped->hEvent;
852c2c66affSColin Finck         }
853c2c66affSColin Finck         else
854c2c66affSColin Finck         {
855c2c66affSColin Finck             /* Using Overlapped Structure and a Completion Routine, so use an APC */
856c2c66affSColin Finck             APCFunction = &AfdAPC; // should be a private io completion function inside us
857c2c66affSColin Finck             APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT));
858c2c66affSColin Finck             if (!APCContext)
859c2c66affSColin Finck             {
860c2c66affSColin Finck                 ERR("Not enough memory for APC Context\n");
861c2c66affSColin Finck                 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, lpNumberOfBytesSent);
862c2c66affSColin Finck             }
863c2c66affSColin Finck             ((PAFDAPCCONTEXT)APCContext)->lpCompletionRoutine = lpCompletionRoutine;
864c2c66affSColin Finck             ((PAFDAPCCONTEXT)APCContext)->lpOverlapped = lpOverlapped;
865c2c66affSColin Finck             ((PAFDAPCCONTEXT)APCContext)->lpSocket = Socket;
866c2c66affSColin Finck             SendInfo.AfdFlags |= AFD_SKIP_FIO;
867c2c66affSColin Finck         }
868c2c66affSColin Finck 
869c2c66affSColin Finck         IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal;
870c2c66affSColin Finck         SendInfo.AfdFlags |= AFD_OVERLAPPED;
871c2c66affSColin Finck     }
872c2c66affSColin Finck 
873c2c66affSColin Finck     /* Send IOCTL */
874c2c66affSColin Finck     Status = NtDeviceIoControlFile((HANDLE)Handle,
875c2c66affSColin Finck                                    Event,
876c2c66affSColin Finck                                    APCFunction,
877c2c66affSColin Finck                                    APCContext,
878c2c66affSColin Finck                                    IOSB,
879c2c66affSColin Finck                                    IOCTL_AFD_SEND_DATAGRAM,
880c2c66affSColin Finck                                    &SendInfo,
881c2c66affSColin Finck                                    sizeof(SendInfo),
882c2c66affSColin Finck                                    NULL,
883c2c66affSColin Finck                                    0);
884c2c66affSColin Finck 
885c2c66affSColin Finck     /* Wait for completion of not overlapped */
886c2c66affSColin Finck     if (Status == STATUS_PENDING && lpOverlapped == NULL)
887c2c66affSColin Finck     {
888c2c66affSColin Finck         /* BUGBUG, shouldn't wait infinitely for send... */
889c2c66affSColin Finck         WaitForSingleObject(SockEvent, INFINITE);
890c2c66affSColin Finck         Status = IOSB->Status;
891c2c66affSColin Finck     }
892c2c66affSColin Finck 
893c2c66affSColin Finck     NtClose(SockEvent);
894c2c66affSColin Finck     HeapFree(GlobalHeap, 0, RemoteAddress);
895c2c66affSColin Finck     if (BindAddress != NULL)
896c2c66affSColin Finck     {
897c2c66affSColin Finck         HeapFree(GlobalHeap, 0, BindAddress);
898c2c66affSColin Finck     }
899c2c66affSColin Finck 
900c2c66affSColin Finck     if (Status == STATUS_PENDING)
901c2c66affSColin Finck     {
902c2c66affSColin Finck         TRACE("Leaving (Pending)\n");
903c2c66affSColin Finck         return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesSent);
904c2c66affSColin Finck     }
905c2c66affSColin Finck 
906c2c66affSColin Finck     SockReenableAsyncSelectEvent(Socket, FD_WRITE);
907c2c66affSColin Finck 
908c2c66affSColin Finck     if (Status == STATUS_SUCCESS && lpOverlapped && lpCompletionRoutine)
909c2c66affSColin Finck     {
910c2c66affSColin Finck         lpCompletionRoutine(Status, IOSB->Information, lpOverlapped, 0);
911c2c66affSColin Finck         HeapFree(GlobalHeap, 0, (PVOID)APCContext);
912c2c66affSColin Finck     }
913c2c66affSColin Finck 
914c2c66affSColin Finck     return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesSent);
915c2c66affSColin Finck }
916c2c66affSColin Finck 
917c2c66affSColin Finck INT
918c2c66affSColin Finck WSPAPI
919c2c66affSColin Finck WSPRecvDisconnect(IN  SOCKET s,
920c2c66affSColin Finck                   OUT LPWSABUF lpInboundDisconnectData,
921c2c66affSColin Finck                   OUT LPINT lpErrno)
922c2c66affSColin Finck {
923c2c66affSColin Finck     UNIMPLEMENTED;
924c2c66affSColin Finck     return 0;
925c2c66affSColin Finck }
926c2c66affSColin Finck 
927c2c66affSColin Finck 
928c2c66affSColin Finck 
929c2c66affSColin Finck INT
930c2c66affSColin Finck WSPAPI
931c2c66affSColin Finck WSPSendDisconnect(IN  SOCKET s,
932c2c66affSColin Finck                   IN  LPWSABUF lpOutboundDisconnectData,
933c2c66affSColin Finck                   OUT LPINT lpErrno)
934c2c66affSColin Finck {
935c2c66affSColin Finck     UNIMPLEMENTED;
936c2c66affSColin Finck     return 0;
937c2c66affSColin Finck }
938c2c66affSColin Finck 
939c2c66affSColin Finck /* EOF */
940