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
26 PSOCKET_INFORMATION Socket
= NULL
;
27 PASYNC_DATA AsyncData
;
31 /* Get the Socket Structure associated to this Socket */
32 Socket
= GetSocketStructure(Handle
);
34 /* Allocate the Async Data Structure to pass on to the Thread later */
35 AsyncData
= HeapAlloc(GetProcessHeap(), 0, sizeof(*AsyncData
));
37 /* Change the Socket to Non Blocking */
39 SetSocketInformation(Socket
, AFD_INFO_BLOCKING_MODE
, &BlockMode
, NULL
);
40 Socket
->SharedData
.NonBlocking
= TRUE
;
42 /* Deactive WSPEventSelect */
43 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) {
62 HeapFree(GetProcessHeap(), 0, AsyncData
);
66 /* Set up the Async Data */
67 AsyncData
->ParentSocket
= Socket
;
68 AsyncData
->SequenceNumber
= Socket
->SharedData
.SequenceNumber
;
70 /* Begin Async Select by using I/O Completion */
71 Status
= NtSetIoCompletion(SockAsyncCompletionPort
,
72 (PVOID
)&SockProcessQueuedAsyncSelect
,
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
) ) return -1;
115 /* Set up the Receive Structure */
116 RecvInfo
.BufferArray
= (PAFD_WSABUF
)lpBuffers
;
117 RecvInfo
.BufferCount
= dwBufferCount
;
118 RecvInfo
.TdiFlags
= 0;
119 RecvInfo
.AfdFlags
= Socket
->SharedData
.NonBlocking
? AFD_IMMEDIATE
: 0;
121 /* Set the TDI Flags */
122 if (*ReceiveFlags
== 0) {
123 RecvInfo
.TdiFlags
|= TDI_RECEIVE_NORMAL
;
127 if (*ReceiveFlags
& MSG_OOB
) {
128 RecvInfo
.TdiFlags
|= TDI_RECEIVE_EXPEDITED
;
130 RecvInfo
.TdiFlags
|= TDI_RECEIVE_NORMAL
;
133 if (*ReceiveFlags
& MSG_PEEK
) {
134 RecvInfo
.TdiFlags
|= TDI_RECEIVE_PEEK
;
137 if (*ReceiveFlags
& MSG_PARTIAL
) {
138 RecvInfo
.TdiFlags
|= TDI_RECEIVE_NORMAL
;
142 /* Verifiy if we should use APC */
144 if (lpOverlapped
== NULL
) {
146 /* Not using Overlapped structure, so use normal blocking on event */
154 if (lpCompletionRoutine
== NULL
) {
156 /* Using Overlapped Structure, but no Completition Routine, so no need for APC */
157 APCContext
= lpOverlapped
;
159 Event
= lpOverlapped
->hEvent
;
163 /* Using Overlapped Structure and a Completition Routine, so use an APC */
164 APCFunction
= NULL
; // should be a private io completition function inside us
165 APCContext
= lpCompletionRoutine
;
166 RecvInfo
.AfdFlags
= AFD_SKIP_FIO
;
169 IOSB
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
170 RecvInfo
.AfdFlags
|= AFD_OVERLAPPED
;
173 IOSB
->Status
= STATUS_PENDING
;
176 Status
= NtDeviceIoControlFile((HANDLE
)Handle
,
187 /* Wait for completition of not overlapped */
188 if (Status
== STATUS_PENDING
&& lpOverlapped
== NULL
) {
189 /* It's up to the protocol to time out recv. We must wait
190 * until the protocol decides it's had enough. */
191 WaitForSingleObject(SockEvent
, INFINITE
);
192 Status
= IOSB
->Status
;
195 NtClose( SockEvent
);
197 AFD_DbgPrint(MID_TRACE
,("Status %x Information %d\n",
198 Status
, IOSB
->Information
));
200 /* Return the Flags */
204 case STATUS_RECEIVE_EXPEDITED
: *ReceiveFlags
= MSG_OOB
; break;
205 case STATUS_RECEIVE_PARTIAL_EXPEDITED
:
206 *ReceiveFlags
= MSG_PARTIAL
| MSG_OOB
; break;
207 case STATUS_RECEIVE_PARTIAL
: *ReceiveFlags
= MSG_PARTIAL
; break;
210 /* Re-enable Async Event */
211 if (*ReceiveFlags
== MSG_OOB
) {
212 SockReenableAsyncSelectEvent(Socket
, FD_OOB
);
214 SockReenableAsyncSelectEvent(Socket
, FD_READ
);
217 return MsafdReturnWithErrno
218 ( Status
, lpErrno
, IOSB
->Information
, lpNumberOfBytesRead
);
227 LPDWORD lpNumberOfBytesRead
,
228 LPDWORD ReceiveFlags
,
229 struct sockaddr
*SocketAddress
,
230 int *SocketAddressLength
,
231 LPWSAOVERLAPPED lpOverlapped
,
232 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
,
233 LPWSATHREADID lpThreadId
,
236 PIO_STATUS_BLOCK IOSB
;
237 IO_STATUS_BLOCK DummyIOSB
;
238 AFD_RECV_INFO_UDP RecvInfo
;
244 PSOCKET_INFORMATION Socket
;
246 /* Get the Socket Structure associate to this Socket*/
247 Socket
= GetSocketStructure(Handle
);
249 Status
= NtCreateEvent( &SockEvent
, GENERIC_READ
| GENERIC_WRITE
,
252 if( !NT_SUCCESS(Status
) ) return -1;
254 /* Set up the Receive Structure */
255 RecvInfo
.BufferArray
= (PAFD_WSABUF
)lpBuffers
;
256 RecvInfo
.BufferCount
= dwBufferCount
;
257 RecvInfo
.TdiFlags
= 0;
258 RecvInfo
.AfdFlags
= Socket
->SharedData
.NonBlocking
? AFD_IMMEDIATE
: 0;
259 RecvInfo
.AddressLength
= SocketAddressLength
;
260 RecvInfo
.Address
= SocketAddress
;
262 /* Set the TDI Flags */
263 if (*ReceiveFlags
== 0) {
264 RecvInfo
.TdiFlags
|= TDI_RECEIVE_NORMAL
;
268 if (*ReceiveFlags
& MSG_OOB
) {
269 RecvInfo
.TdiFlags
|= TDI_RECEIVE_EXPEDITED
;
271 RecvInfo
.TdiFlags
|= TDI_RECEIVE_NORMAL
;
274 if (*ReceiveFlags
& MSG_PEEK
) {
275 RecvInfo
.TdiFlags
|= TDI_RECEIVE_PEEK
;
278 if (*ReceiveFlags
& MSG_PARTIAL
) {
279 RecvInfo
.TdiFlags
|= TDI_RECEIVE_NORMAL
;
283 /* Verifiy if we should use APC */
285 if (lpOverlapped
== NULL
) {
287 /* Not using Overlapped structure, so use normal blocking on event */
295 if (lpCompletionRoutine
== NULL
) {
297 /* Using Overlapped Structure, but no Completition Routine, so no need for APC */
298 APCContext
= lpOverlapped
;
300 Event
= lpOverlapped
->hEvent
;
304 /* Using Overlapped Structure and a Completition Routine, so use an APC */
305 APCFunction
= NULL
; // should be a private io completition function inside us
306 APCContext
= lpCompletionRoutine
;
307 RecvInfo
.AfdFlags
= AFD_SKIP_FIO
;
310 IOSB
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
311 RecvInfo
.AfdFlags
|= AFD_OVERLAPPED
;
314 IOSB
->Status
= STATUS_PENDING
;
317 Status
= NtDeviceIoControlFile((HANDLE
)Handle
,
322 IOCTL_AFD_RECV_DATAGRAM
,
328 /* Wait for completition of not overlapped */
329 if (Status
== STATUS_PENDING
&& lpOverlapped
== NULL
) {
330 WaitForSingleObject(SockEvent
, INFINITE
); // BUGBUG, shouldn wait infintely for receive...
331 Status
= IOSB
->Status
;
334 NtClose( SockEvent
);
336 /* Return the Flags */
340 case STATUS_RECEIVE_EXPEDITED
: *ReceiveFlags
= MSG_OOB
; break;
341 case STATUS_RECEIVE_PARTIAL_EXPEDITED
:
342 *ReceiveFlags
= MSG_PARTIAL
| MSG_OOB
; break;
343 case STATUS_RECEIVE_PARTIAL
: *ReceiveFlags
= MSG_PARTIAL
; break;
346 /* Re-enable Async Event */
347 SockReenableAsyncSelectEvent(Socket
, FD_READ
);
349 return MsafdReturnWithErrno
350 ( Status
, lpErrno
, IOSB
->Information
, lpNumberOfBytesRead
);
360 LPDWORD lpNumberOfBytesSent
,
362 LPWSAOVERLAPPED lpOverlapped
,
363 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
,
364 LPWSATHREADID lpThreadId
,
367 PIO_STATUS_BLOCK IOSB
;
368 IO_STATUS_BLOCK DummyIOSB
;
369 AFD_SEND_INFO SendInfo
;
375 PSOCKET_INFORMATION Socket
;
377 /* Get the Socket Structure associate to this Socket*/
378 Socket
= GetSocketStructure(Handle
);
380 Status
= NtCreateEvent( &SockEvent
, GENERIC_READ
| GENERIC_WRITE
,
383 if( !NT_SUCCESS(Status
) ) return -1;
385 AFD_DbgPrint(MID_TRACE
,("Called\n"));
387 /* Set up the Send Structure */
388 SendInfo
.BufferArray
= (PAFD_WSABUF
)lpBuffers
;
389 SendInfo
.BufferCount
= dwBufferCount
;
390 SendInfo
.TdiFlags
= 0;
391 SendInfo
.AfdFlags
= Socket
->SharedData
.NonBlocking
? AFD_IMMEDIATE
: 0;
393 /* Set the TDI Flags */
395 if (iFlags
& MSG_OOB
) {
396 SendInfo
.TdiFlags
|= TDI_SEND_EXPEDITED
;
398 if (iFlags
& MSG_PARTIAL
) {
399 SendInfo
.TdiFlags
|= TDI_SEND_PARTIAL
;
403 /* Verifiy if we should use APC */
404 if (lpOverlapped
== NULL
) {
406 /* Not using Overlapped structure, so use normal blocking on event */
414 if (lpCompletionRoutine
== NULL
) {
416 /* Using Overlapped Structure, but no Completition Routine, so no need for APC */
417 APCContext
= lpOverlapped
;
419 Event
= lpOverlapped
->hEvent
;
423 /* Using Overlapped Structure and a Completition Routine, so use an APC */
424 APCFunction
= NULL
; // should be a private io completition function inside us
425 APCContext
= lpCompletionRoutine
;
426 SendInfo
.AfdFlags
= AFD_SKIP_FIO
;
429 IOSB
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
430 SendInfo
.AfdFlags
|= AFD_OVERLAPPED
;
433 IOSB
->Status
= STATUS_PENDING
;
436 Status
= NtDeviceIoControlFile((HANDLE
)Handle
,
447 /* Wait for completition of not overlapped */
448 if (Status
== STATUS_PENDING
&& lpOverlapped
== NULL
) {
449 WaitForSingleObject(SockEvent
, INFINITE
); // BUGBUG, shouldn wait infintely for send...
450 Status
= IOSB
->Status
;
453 NtClose( SockEvent
);
455 if (Status
== STATUS_PENDING
) {
456 AFD_DbgPrint(MID_TRACE
,("Leaving (Pending)\n"));
457 return WSA_IO_PENDING
;
460 /* Re-enable Async Event */
461 SockReenableAsyncSelectEvent(Socket
, FD_WRITE
);
463 AFD_DbgPrint(MID_TRACE
,("Leaving (Success, %d)\n", IOSB
->Information
));
465 return MsafdReturnWithErrno
466 ( Status
, lpErrno
, IOSB
->Information
, lpNumberOfBytesSent
);
475 LPDWORD lpNumberOfBytesSent
,
477 const struct sockaddr
*SocketAddress
,
478 int SocketAddressLength
,
479 LPWSAOVERLAPPED lpOverlapped
,
480 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
,
481 LPWSATHREADID lpThreadId
,
484 PIO_STATUS_BLOCK IOSB
;
485 IO_STATUS_BLOCK DummyIOSB
;
486 AFD_SEND_INFO_UDP SendInfo
;
491 PTRANSPORT_ADDRESS RemoteAddress
;
492 UCHAR TdiBuffer
[0x16];
493 PSOCKADDR BindAddress
;
494 INT BindAddressLength
;
496 PSOCKET_INFORMATION Socket
;
499 /* Get the Socket Structure associate to this Socket*/
500 Socket
= GetSocketStructure(Handle
);
502 Status
= NtCreateEvent( &SockEvent
, GENERIC_READ
| GENERIC_WRITE
,
505 if( !NT_SUCCESS(Status
) ) return -1;
508 if (Socket
->SharedData
.State
== SocketOpen
) {
510 /* Get the Wildcard Address */
511 BindAddressLength
= Socket
->HelperData
->MaxWSAddressLength
;
512 BindAddress
= HeapAlloc(GlobalHeap
, 0, BindAddressLength
);
513 Socket
->HelperData
->WSHGetWildcardSockaddr (Socket
->HelperContext
,
518 WSPBind(Handle
, BindAddress
, BindAddressLength
, NULL
);
521 /* Set up Address in TDI Format */
522 RemoteAddress
= (PTRANSPORT_ADDRESS
)TdiBuffer
;
523 RemoteAddress
->TAAddressCount
= 1;
524 RemoteAddress
->Address
[0].AddressLength
= SocketAddressLength
- sizeof(SocketAddress
->sa_family
);
525 RtlCopyMemory(&RemoteAddress
->Address
[0].AddressType
, SocketAddress
, SocketAddressLength
);
527 /* Set up Structure */
528 SendInfo
.BufferArray
= (PAFD_WSABUF
)lpBuffers
;
529 SendInfo
.AfdFlags
= Socket
->SharedData
.NonBlocking
? AFD_IMMEDIATE
: 0;
530 SendInfo
.BufferCount
= dwBufferCount
;
531 SendInfo
.RemoteAddress
= RemoteAddress
;
532 SendInfo
.SizeOfRemoteAddress
= Socket
->HelperData
->MaxTDIAddressLength
;
534 /* Verifiy if we should use APC */
535 if (lpOverlapped
== NULL
) {
537 /* Not using Overlapped structure, so use normal blocking on event */
545 if (lpCompletionRoutine
== NULL
) {
547 /* Using Overlapped Structure, but no Completition Routine, so no need for APC */
548 APCContext
= lpOverlapped
;
550 Event
= lpOverlapped
->hEvent
;
554 /* Using Overlapped Structure and a Completition Routine, so use an APC */
555 APCFunction
= NULL
; // should be a private io completition function inside us
556 APCContext
= lpCompletionRoutine
;
557 SendInfo
.AfdFlags
= AFD_SKIP_FIO
;
560 IOSB
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
561 SendInfo
.AfdFlags
|= AFD_OVERLAPPED
;
565 Status
= NtDeviceIoControlFile((HANDLE
)Handle
,
570 IOCTL_AFD_SEND_DATAGRAM
,
576 /* Wait for completition of not overlapped */
577 if (Status
== STATUS_PENDING
&& lpOverlapped
== NULL
) {
578 WaitForSingleObject(SockEvent
, INFINITE
); // BUGBUG, shouldn wait infintely for send...
579 Status
= IOSB
->Status
;
582 NtClose( SockEvent
);
584 if (Status
== STATUS_PENDING
) {
585 return WSA_IO_PENDING
;
588 /* Re-enable Async Event */
589 SockReenableAsyncSelectEvent(Socket
, FD_WRITE
);
591 return MsafdReturnWithErrno
592 ( Status
, lpErrno
, IOSB
->Information
, lpNumberOfBytesSent
);
598 OUT LPWSABUF lpInboundDisconnectData
,
612 IN LPWSABUF lpOutboundDisconnectData
,