2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Ancillary Function Driver DLL
5 * PURPOSE: Send/receive routines
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Alex Ionescu (alex@relsoft.net)
9 * CSH 01/09-2000 Created
10 * Alex 16/07/2004 - Complete Rewrite
19 WSPAsyncSelect(IN SOCKET Handle
,
25 PSOCKET_INFORMATION Socket
= NULL
;
26 PASYNC_DATA AsyncData
;
30 /* Get the Socket Structure associated to this Socket */
31 Socket
= GetSocketStructure(Handle
);
33 /* Allocate the Async Data Structure to pass on to the Thread later */
34 AsyncData
= HeapAlloc(GetProcessHeap(), 0, sizeof(*AsyncData
));
36 /* Change the Socket to Non Blocking */
38 SetSocketInformation(Socket
, AFD_INFO_BLOCKING_MODE
, &BlockMode
, NULL
);
39 Socket
->SharedData
.NonBlocking
= TRUE
;
41 /* Deactive WSPEventSelect */
42 if (Socket
->SharedData
.AsyncEvents
)
44 WSPEventSelect(Handle
, NULL
, 0, NULL
);
47 /* Create the Asynch Thread if Needed */
48 SockCreateOrReferenceAsyncThread();
50 /* Open a Handle to AFD's Async Helper */
51 SockGetAsyncSelectHelperAfdHandle();
53 /* Store Socket Data */
54 Socket
->SharedData
.hWnd
= hWnd
;
55 Socket
->SharedData
.wMsg
= wMsg
;
56 Socket
->SharedData
.AsyncEvents
= lEvent
;
57 Socket
->SharedData
.AsyncDisabledEvents
= 0;
58 Socket
->SharedData
.SequenceNumber
++;
60 /* Return if there are no more Events */
61 if ((Socket
->SharedData
.AsyncEvents
& (~Socket
->SharedData
.AsyncDisabledEvents
)) == 0)
63 HeapFree(GetProcessHeap(), 0, AsyncData
);
67 /* Set up the Async Data */
68 AsyncData
->ParentSocket
= Socket
;
69 AsyncData
->SequenceNumber
= Socket
->SharedData
.SequenceNumber
;
71 /* Begin Async Select by using I/O Completion */
72 Status
= NtSetIoCompletion(SockAsyncCompletionPort
,
73 (PVOID
)&SockProcessQueuedAsyncSelect
,
85 WSPRecv(SOCKET Handle
,
88 LPDWORD lpNumberOfBytesRead
,
90 LPWSAOVERLAPPED lpOverlapped
,
91 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
,
92 LPWSATHREADID lpThreadId
,
95 PIO_STATUS_BLOCK IOSB
;
96 IO_STATUS_BLOCK DummyIOSB
;
97 AFD_RECV_INFO RecvInfo
;
103 PSOCKET_INFORMATION Socket
;
105 AFD_DbgPrint(MID_TRACE
,("Called (%x)\n", Handle
));
107 /* Get the Socket Structure associate to this Socket*/
108 Socket
= GetSocketStructure(Handle
);
110 Status
= NtCreateEvent( &SockEvent
, GENERIC_READ
| GENERIC_WRITE
,
113 if( !NT_SUCCESS(Status
) )
116 /* Set up the Receive Structure */
117 RecvInfo
.BufferArray
= (PAFD_WSABUF
)lpBuffers
;
118 RecvInfo
.BufferCount
= dwBufferCount
;
119 RecvInfo
.TdiFlags
= 0;
120 RecvInfo
.AfdFlags
= Socket
->SharedData
.NonBlocking
? AFD_IMMEDIATE
: 0;
122 /* Set the TDI Flags */
123 if (*ReceiveFlags
== 0)
125 RecvInfo
.TdiFlags
|= TDI_RECEIVE_NORMAL
;
129 if (*ReceiveFlags
& MSG_OOB
)
131 RecvInfo
.TdiFlags
|= TDI_RECEIVE_EXPEDITED
;
135 RecvInfo
.TdiFlags
|= TDI_RECEIVE_NORMAL
;
138 if (*ReceiveFlags
& MSG_PEEK
)
140 RecvInfo
.TdiFlags
|= TDI_RECEIVE_PEEK
;
143 if (*ReceiveFlags
& MSG_PARTIAL
) {
144 RecvInfo
.TdiFlags
|= TDI_RECEIVE_NORMAL
;
148 /* Verifiy if we should use APC */
150 if (lpOverlapped
== NULL
)
152 /* Not using Overlapped structure, so use normal blocking on event */
160 if (lpCompletionRoutine
== NULL
)
162 /* Using Overlapped Structure, but no Completition Routine, so no need for APC */
163 APCContext
= lpOverlapped
;
165 Event
= lpOverlapped
->hEvent
;
169 /* Using Overlapped Structure and a Completition Routine, so use an APC */
170 APCFunction
= NULL
; // should be a private io completition function inside us
171 APCContext
= lpCompletionRoutine
;
172 RecvInfo
.AfdFlags
= AFD_SKIP_FIO
;
175 IOSB
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
176 RecvInfo
.AfdFlags
|= AFD_OVERLAPPED
;
179 IOSB
->Status
= STATUS_PENDING
;
182 Status
= NtDeviceIoControlFile((HANDLE
)Handle
,
193 /* Wait for completition of not overlapped */
194 if (Status
== STATUS_PENDING
&& lpOverlapped
== NULL
)
196 /* It's up to the protocol to time out recv. We must wait
197 * until the protocol decides it's had enough.
199 WaitForSingleObject(SockEvent
, INFINITE
);
200 Status
= IOSB
->Status
;
203 NtClose( SockEvent
);
205 AFD_DbgPrint(MID_TRACE
,("Status %x Information %d\n", Status
, IOSB
->Information
));
207 /* Return the Flags */
212 case STATUS_RECEIVE_EXPEDITED
:
213 *ReceiveFlags
= MSG_OOB
;
215 case STATUS_RECEIVE_PARTIAL_EXPEDITED
:
216 *ReceiveFlags
= MSG_PARTIAL
| MSG_OOB
;
218 case STATUS_RECEIVE_PARTIAL
:
219 *ReceiveFlags
= MSG_PARTIAL
;
223 /* Re-enable Async Event */
224 if (*ReceiveFlags
== MSG_OOB
)
226 SockReenableAsyncSelectEvent(Socket
, FD_OOB
);
230 SockReenableAsyncSelectEvent(Socket
, FD_READ
);
233 return MsafdReturnWithErrno ( Status
, lpErrno
, IOSB
->Information
, lpNumberOfBytesRead
);
238 WSPRecvFrom(SOCKET Handle
,
241 LPDWORD lpNumberOfBytesRead
,
242 LPDWORD ReceiveFlags
,
243 struct sockaddr
*SocketAddress
,
244 int *SocketAddressLength
,
245 LPWSAOVERLAPPED lpOverlapped
,
246 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
,
247 LPWSATHREADID lpThreadId
,
250 PIO_STATUS_BLOCK IOSB
;
251 IO_STATUS_BLOCK DummyIOSB
;
252 AFD_RECV_INFO_UDP RecvInfo
;
258 PSOCKET_INFORMATION Socket
;
260 /* Get the Socket Structure associate to this Socket*/
261 Socket
= GetSocketStructure(Handle
);
263 Status
= NtCreateEvent( &SockEvent
, GENERIC_READ
| GENERIC_WRITE
,
266 if( !NT_SUCCESS(Status
) )
269 /* Set up the Receive Structure */
270 RecvInfo
.BufferArray
= (PAFD_WSABUF
)lpBuffers
;
271 RecvInfo
.BufferCount
= dwBufferCount
;
272 RecvInfo
.TdiFlags
= 0;
273 RecvInfo
.AfdFlags
= Socket
->SharedData
.NonBlocking
? AFD_IMMEDIATE
: 0;
274 RecvInfo
.AddressLength
= SocketAddressLength
;
275 RecvInfo
.Address
= SocketAddress
;
277 /* Set the TDI Flags */
278 if (*ReceiveFlags
== 0)
280 RecvInfo
.TdiFlags
|= TDI_RECEIVE_NORMAL
;
284 if (*ReceiveFlags
& MSG_OOB
)
286 RecvInfo
.TdiFlags
|= TDI_RECEIVE_EXPEDITED
;
290 RecvInfo
.TdiFlags
|= TDI_RECEIVE_NORMAL
;
293 if (*ReceiveFlags
& MSG_PEEK
)
295 RecvInfo
.TdiFlags
|= TDI_RECEIVE_PEEK
;
298 if (*ReceiveFlags
& MSG_PARTIAL
)
300 RecvInfo
.TdiFlags
|= TDI_RECEIVE_NORMAL
;
304 /* Verifiy if we should use APC */
306 if (lpOverlapped
== NULL
)
308 /* Not using Overlapped structure, so use normal blocking on event */
316 if (lpCompletionRoutine
== NULL
)
318 /* Using Overlapped Structure, but no Completition Routine, so no need for APC */
319 APCContext
= lpOverlapped
;
321 Event
= lpOverlapped
->hEvent
;
325 /* Using Overlapped Structure and a Completition Routine, so use an APC */
326 APCFunction
= NULL
; // should be a private io completition function inside us
327 APCContext
= lpCompletionRoutine
;
328 RecvInfo
.AfdFlags
= AFD_SKIP_FIO
;
331 IOSB
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
332 RecvInfo
.AfdFlags
|= AFD_OVERLAPPED
;
335 IOSB
->Status
= STATUS_PENDING
;
338 Status
= NtDeviceIoControlFile((HANDLE
)Handle
,
343 IOCTL_AFD_RECV_DATAGRAM
,
349 /* Wait for completition of not overlapped */
350 if (Status
== STATUS_PENDING
&& lpOverlapped
== NULL
)
352 WaitForSingleObject(SockEvent
, INFINITE
); // BUGBUG, shouldn wait infintely for receive...
353 Status
= IOSB
->Status
;
356 NtClose( SockEvent
);
358 /* Return the Flags */
363 case STATUS_RECEIVE_EXPEDITED
: *ReceiveFlags
= MSG_OOB
;
365 case STATUS_RECEIVE_PARTIAL_EXPEDITED
:
366 *ReceiveFlags
= MSG_PARTIAL
| MSG_OOB
;
368 case STATUS_RECEIVE_PARTIAL
:
369 *ReceiveFlags
= MSG_PARTIAL
;
373 /* Re-enable Async Event */
374 SockReenableAsyncSelectEvent(Socket
, FD_READ
);
376 return MsafdReturnWithErrno ( Status
, lpErrno
, IOSB
->Information
, lpNumberOfBytesRead
);
382 WSPSend(SOCKET Handle
,
385 LPDWORD lpNumberOfBytesSent
,
387 LPWSAOVERLAPPED lpOverlapped
,
388 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
,
389 LPWSATHREADID lpThreadId
,
392 PIO_STATUS_BLOCK IOSB
;
393 IO_STATUS_BLOCK DummyIOSB
;
394 AFD_SEND_INFO SendInfo
;
400 PSOCKET_INFORMATION Socket
;
402 /* Get the Socket Structure associate to this Socket*/
403 Socket
= GetSocketStructure(Handle
);
405 Status
= NtCreateEvent( &SockEvent
, GENERIC_READ
| GENERIC_WRITE
,
408 if( !NT_SUCCESS(Status
) )
411 AFD_DbgPrint(MID_TRACE
,("Called\n"));
413 /* Set up the Send Structure */
414 SendInfo
.BufferArray
= (PAFD_WSABUF
)lpBuffers
;
415 SendInfo
.BufferCount
= dwBufferCount
;
416 SendInfo
.TdiFlags
= 0;
417 SendInfo
.AfdFlags
= Socket
->SharedData
.NonBlocking
? AFD_IMMEDIATE
: 0;
419 /* Set the TDI Flags */
422 if (iFlags
& MSG_OOB
)
424 SendInfo
.TdiFlags
|= TDI_SEND_EXPEDITED
;
426 if (iFlags
& MSG_PARTIAL
)
428 SendInfo
.TdiFlags
|= TDI_SEND_PARTIAL
;
432 /* Verifiy if we should use APC */
433 if (lpOverlapped
== NULL
)
435 /* Not using Overlapped structure, so use normal blocking on event */
443 if (lpCompletionRoutine
== NULL
)
445 /* Using Overlapped Structure, but no Completition Routine, so no need for APC */
446 APCContext
= lpOverlapped
;
448 Event
= lpOverlapped
->hEvent
;
452 /* Using Overlapped Structure and a Completition Routine, so use an APC */
453 APCFunction
= NULL
; // should be a private io completition function inside us
454 APCContext
= lpCompletionRoutine
;
455 SendInfo
.AfdFlags
= AFD_SKIP_FIO
;
458 IOSB
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
459 SendInfo
.AfdFlags
|= AFD_OVERLAPPED
;
462 IOSB
->Status
= STATUS_PENDING
;
465 Status
= NtDeviceIoControlFile((HANDLE
)Handle
,
476 /* Wait for completition of not overlapped */
477 if (Status
== STATUS_PENDING
&& lpOverlapped
== NULL
)
479 WaitForSingleObject(SockEvent
, INFINITE
); // BUGBUG, shouldn wait infintely for send...
480 Status
= IOSB
->Status
;
483 NtClose( SockEvent
);
485 if (Status
== STATUS_PENDING
)
487 AFD_DbgPrint(MID_TRACE
,("Leaving (Pending)\n"));
488 return WSA_IO_PENDING
;
491 /* Re-enable Async Event */
492 SockReenableAsyncSelectEvent(Socket
, FD_WRITE
);
494 AFD_DbgPrint(MID_TRACE
,("Leaving (Success, %d)\n", IOSB
->Information
));
496 return MsafdReturnWithErrno( Status
, lpErrno
, IOSB
->Information
, lpNumberOfBytesSent
);
501 WSPSendTo(SOCKET Handle
,
504 LPDWORD lpNumberOfBytesSent
,
506 const struct sockaddr
*SocketAddress
,
507 int SocketAddressLength
,
508 LPWSAOVERLAPPED lpOverlapped
,
509 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
,
510 LPWSATHREADID lpThreadId
,
513 PIO_STATUS_BLOCK IOSB
;
514 IO_STATUS_BLOCK DummyIOSB
;
515 AFD_SEND_INFO_UDP SendInfo
;
520 PTRANSPORT_ADDRESS RemoteAddress
;
521 UCHAR TdiBuffer
[0x16];
522 PSOCKADDR BindAddress
;
523 INT BindAddressLength
;
525 PSOCKET_INFORMATION Socket
;
528 /* Get the Socket Structure associate to this Socket*/
529 Socket
= GetSocketStructure(Handle
);
531 Status
= NtCreateEvent( &SockEvent
, GENERIC_READ
| GENERIC_WRITE
,
534 if( !NT_SUCCESS(Status
) )
538 if (Socket
->SharedData
.State
== SocketOpen
)
540 /* Get the Wildcard Address */
541 BindAddressLength
= Socket
->HelperData
->MaxWSAddressLength
;
542 BindAddress
= HeapAlloc(GlobalHeap
, 0, BindAddressLength
);
543 Socket
->HelperData
->WSHGetWildcardSockaddr (Socket
->HelperContext
,
548 WSPBind(Handle
, BindAddress
, BindAddressLength
, NULL
);
551 /* Set up Address in TDI Format */
552 RemoteAddress
= (PTRANSPORT_ADDRESS
)TdiBuffer
;
553 RemoteAddress
->TAAddressCount
= 1;
554 RemoteAddress
->Address
[0].AddressLength
= SocketAddressLength
- sizeof(SocketAddress
->sa_family
);
555 RtlCopyMemory(&RemoteAddress
->Address
[0].AddressType
, SocketAddress
, SocketAddressLength
);
557 /* Set up Structure */
558 SendInfo
.BufferArray
= (PAFD_WSABUF
)lpBuffers
;
559 SendInfo
.AfdFlags
= Socket
->SharedData
.NonBlocking
? AFD_IMMEDIATE
: 0;
560 SendInfo
.BufferCount
= dwBufferCount
;
561 SendInfo
.RemoteAddress
= RemoteAddress
;
562 SendInfo
.SizeOfRemoteAddress
= Socket
->HelperData
->MaxTDIAddressLength
;
564 /* Verifiy if we should use APC */
565 if (lpOverlapped
== NULL
)
567 /* Not using Overlapped structure, so use normal blocking on event */
575 if (lpCompletionRoutine
== NULL
)
577 /* Using Overlapped Structure, but no Completition Routine, so no need for APC */
578 APCContext
= lpOverlapped
;
580 Event
= lpOverlapped
->hEvent
;
584 /* Using Overlapped Structure and a Completition Routine, so use an APC */
585 APCFunction
= NULL
; // should be a private io completition function inside us
586 APCContext
= lpCompletionRoutine
;
587 SendInfo
.AfdFlags
= AFD_SKIP_FIO
;
590 IOSB
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
591 SendInfo
.AfdFlags
|= AFD_OVERLAPPED
;
595 Status
= NtDeviceIoControlFile((HANDLE
)Handle
,
600 IOCTL_AFD_SEND_DATAGRAM
,
606 /* Wait for completition of not overlapped */
607 if (Status
== STATUS_PENDING
&& lpOverlapped
== NULL
)
609 WaitForSingleObject(SockEvent
, INFINITE
); // BUGBUG, shouldn wait infintely for send...
610 Status
= IOSB
->Status
;
613 NtClose( SockEvent
);
615 if (Status
== STATUS_PENDING
)
616 return WSA_IO_PENDING
;
619 /* Re-enable Async Event */
620 SockReenableAsyncSelectEvent(Socket
, FD_WRITE
);
622 return MsafdReturnWithErrno ( Status
, lpErrno
, IOSB
->Information
, lpNumberOfBytesSent
);
626 WSPRecvDisconnect(IN SOCKET s
,
627 OUT LPWSABUF lpInboundDisconnectData
,
638 WSPSendDisconnect(IN SOCKET s
,
639 IN LPWSABUF lpOutboundDisconnectData
,