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
36 LPDWORD lpNumberOfBytesRead
,
38 LPWSAOVERLAPPED lpOverlapped
,
39 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
,
40 LPWSATHREADID lpThreadId
,
43 PIO_STATUS_BLOCK IOSB
;
44 IO_STATUS_BLOCK DummyIOSB
;
45 AFD_RECV_INFO RecvInfo
;
51 PSOCKET_INFORMATION Socket
;
54 /* Get the Socket Structure associate to this Socket*/
55 Socket
= GetSocketStructure(Handle
);
57 Status
= NtCreateEvent( &SockEvent
, GENERIC_READ
| GENERIC_WRITE
,
60 if( !NT_SUCCESS(Status
) ) return -1;
62 /* Set up the Receive Structure */
63 RecvInfo
.BufferArray
= (PAFD_WSABUF
)lpBuffers
;
64 RecvInfo
.BufferCount
= dwBufferCount
;
65 RecvInfo
.TdiFlags
= 0;
66 RecvInfo
.AfdFlags
= Socket
->SharedData
.NonBlocking
? AFD_IMMEDIATE
: 0;
68 /* Set the TDI Flags */
69 if (*ReceiveFlags
== 0) {
70 RecvInfo
.TdiFlags
|= TDI_RECEIVE_NORMAL
;
74 if (*ReceiveFlags
& MSG_OOB
) {
75 RecvInfo
.TdiFlags
|= TDI_RECEIVE_EXPEDITED
;
77 RecvInfo
.TdiFlags
|= TDI_RECEIVE_NORMAL
;
80 if (*ReceiveFlags
& MSG_PEEK
) {
81 RecvInfo
.TdiFlags
|= TDI_RECEIVE_PEEK
;
84 if (*ReceiveFlags
& MSG_PARTIAL
) {
85 RecvInfo
.TdiFlags
|= TDI_RECEIVE_NORMAL
;
89 /* Verifiy if we should use APC */
91 if (lpOverlapped
== NULL
) {
93 /* Not using Overlapped structure, so use normal blocking on event */
101 if (lpCompletionRoutine
== NULL
) {
103 /* Using Overlapped Structure, but no Completition Routine, so no need for APC */
104 APCContext
= lpOverlapped
;
106 Event
= lpOverlapped
->hEvent
;
110 /* Using Overlapped Structure and a Completition Routine, so use an APC */
111 APCFunction
= NULL
; // should be a private io completition function inside us
112 APCContext
= lpCompletionRoutine
;
113 RecvInfo
.AfdFlags
= AFD_SKIP_FIO
;
116 IOSB
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
117 RecvInfo
.AfdFlags
|= AFD_OVERLAPPED
;
120 IOSB
->Status
= STATUS_PENDING
;
123 Status
= NtDeviceIoControlFile((HANDLE
)Handle
,
134 /* Wait for completition of not overlapped */
135 if (Status
== STATUS_PENDING
&& lpOverlapped
== NULL
) {
136 WaitForSingleObject(SockEvent
, 0); // BUGBUG, shouldn wait infintely for receive...
137 Status
= IOSB
->Status
;
140 NtClose( SockEvent
);
142 /* Return the Flags */
145 case STATUS_CANT_WAIT
:
146 return WSAEWOULDBLOCK
;
151 case STATUS_PENDING
:
152 return WSA_IO_PENDING
;
154 case STATUS_BUFFER_OVERFLOW
:
157 case STATUS_RECEIVE_EXPEDITED
:
158 *ReceiveFlags
= MSG_OOB
;
161 case STATUS_RECEIVE_PARTIAL_EXPEDITED
:
162 *ReceiveFlags
= MSG_PARTIAL
| MSG_OOB
;
165 case STATUS_RECEIVE_PARTIAL
:
166 *ReceiveFlags
= MSG_PARTIAL
;
170 /* Return Number of bytes Read */
171 *lpNumberOfBytesRead
= (DWORD
)IOSB
->Information
;
174 return STATUS_SUCCESS
;
183 LPDWORD lpNumberOfBytesRead
,
184 LPDWORD ReceiveFlags
,
185 struct sockaddr
*SocketAddress
,
186 int *SocketAddressLength
,
187 LPWSAOVERLAPPED lpOverlapped
,
188 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
,
189 LPWSATHREADID lpThreadId
,
192 PIO_STATUS_BLOCK IOSB
;
193 IO_STATUS_BLOCK DummyIOSB
;
194 AFD_RECV_INFO_UDP RecvInfo
;
200 PSOCKET_INFORMATION Socket
;
202 /* Get the Socket Structure associate to this Socket*/
203 Socket
= GetSocketStructure(Handle
);
205 Status
= NtCreateEvent( &SockEvent
, GENERIC_READ
| GENERIC_WRITE
,
208 if( !NT_SUCCESS(Status
) ) return -1;
210 /* Set up the Receive Structure */
211 RecvInfo
.BufferArray
= (PAFD_WSABUF
)lpBuffers
;
212 RecvInfo
.BufferCount
= dwBufferCount
;
213 RecvInfo
.TdiFlags
= 0;
214 RecvInfo
.AfdFlags
= Socket
->SharedData
.NonBlocking
? AFD_IMMEDIATE
: 0;
215 RecvInfo
.AddressLength
= SocketAddressLength
;
216 RecvInfo
.Address
= SocketAddress
;
218 /* Set the TDI Flags */
219 if (*ReceiveFlags
== 0) {
220 RecvInfo
.TdiFlags
|= TDI_RECEIVE_NORMAL
;
224 if (*ReceiveFlags
& MSG_OOB
) {
225 RecvInfo
.TdiFlags
|= TDI_RECEIVE_EXPEDITED
;
227 RecvInfo
.TdiFlags
|= TDI_RECEIVE_NORMAL
;
230 if (*ReceiveFlags
& MSG_PEEK
) {
231 RecvInfo
.TdiFlags
|= TDI_RECEIVE_PEEK
;
234 if (*ReceiveFlags
& MSG_PARTIAL
) {
235 RecvInfo
.TdiFlags
|= TDI_RECEIVE_NORMAL
;
239 /* Verifiy if we should use APC */
241 if (lpOverlapped
== NULL
) {
243 /* Not using Overlapped structure, so use normal blocking on event */
251 if (lpCompletionRoutine
== NULL
) {
253 /* Using Overlapped Structure, but no Completition Routine, so no need for APC */
254 APCContext
= lpOverlapped
;
256 Event
= lpOverlapped
->hEvent
;
260 /* Using Overlapped Structure and a Completition Routine, so use an APC */
261 APCFunction
= NULL
; // should be a private io completition function inside us
262 APCContext
= lpCompletionRoutine
;
263 RecvInfo
.AfdFlags
= AFD_SKIP_FIO
;
266 IOSB
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
267 RecvInfo
.AfdFlags
|= AFD_OVERLAPPED
;
270 IOSB
->Status
= STATUS_PENDING
;
273 Status
= NtDeviceIoControlFile((HANDLE
)Handle
,
278 IOCTL_AFD_RECV_DATAGRAM
,
284 /* Wait for completition of not overlapped */
285 if (Status
== STATUS_PENDING
&& lpOverlapped
== NULL
) {
286 WaitForSingleObject(SockEvent
, 0); // BUGBUG, shouldn wait infintely for receive...
287 Status
= IOSB
->Status
;
290 NtClose( SockEvent
);
292 /* Return the Flags */
295 case STATUS_CANT_WAIT
:
296 return WSAEWOULDBLOCK
;
301 case STATUS_PENDING
:
302 return WSA_IO_PENDING
;
304 case STATUS_BUFFER_OVERFLOW
:
307 case STATUS_RECEIVE_EXPEDITED
:
308 *ReceiveFlags
= MSG_OOB
;
311 case STATUS_RECEIVE_PARTIAL_EXPEDITED
:
312 *ReceiveFlags
= MSG_PARTIAL
| MSG_OOB
;
315 case STATUS_RECEIVE_PARTIAL
:
316 *ReceiveFlags
= MSG_PARTIAL
;
320 /* Return Number of bytes Read */
321 *lpNumberOfBytesRead
= (DWORD
)IOSB
->Information
;
324 return STATUS_SUCCESS
;
334 LPDWORD lpNumberOfBytesSent
,
336 LPWSAOVERLAPPED lpOverlapped
,
337 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
,
338 LPWSATHREADID lpThreadId
,
341 PIO_STATUS_BLOCK IOSB
;
342 IO_STATUS_BLOCK DummyIOSB
;
343 AFD_SEND_INFO SendInfo
;
349 PSOCKET_INFORMATION Socket
;
351 /* Get the Socket Structure associate to this Socket*/
352 Socket
= GetSocketStructure(Handle
);
354 Status
= NtCreateEvent( &SockEvent
, GENERIC_READ
| GENERIC_WRITE
,
357 if( !NT_SUCCESS(Status
) ) return -1;
359 AFD_DbgPrint(MID_TRACE
,("Called\n"));
361 /* Set up the Send Structure */
362 SendInfo
.BufferArray
= (PAFD_WSABUF
)lpBuffers
;
363 SendInfo
.BufferCount
= dwBufferCount
;
364 SendInfo
.TdiFlags
= 0;
365 SendInfo
.AfdFlags
= Socket
->SharedData
.NonBlocking
? AFD_IMMEDIATE
: 0;
367 /* Set the TDI Flags */
369 if (iFlags
& MSG_OOB
) {
370 SendInfo
.TdiFlags
|= TDI_SEND_EXPEDITED
;
372 if (iFlags
& MSG_PARTIAL
) {
373 SendInfo
.TdiFlags
|= TDI_SEND_PARTIAL
;
377 /* Verifiy if we should use APC */
378 if (lpOverlapped
== NULL
) {
380 /* Not using Overlapped structure, so use normal blocking on event */
388 if (lpCompletionRoutine
== NULL
) {
390 /* Using Overlapped Structure, but no Completition Routine, so no need for APC */
391 APCContext
= lpOverlapped
;
393 Event
= lpOverlapped
->hEvent
;
397 /* Using Overlapped Structure and a Completition Routine, so use an APC */
398 APCFunction
= NULL
; // should be a private io completition function inside us
399 APCContext
= lpCompletionRoutine
;
400 SendInfo
.AfdFlags
= AFD_SKIP_FIO
;
403 IOSB
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
404 SendInfo
.AfdFlags
|= AFD_OVERLAPPED
;
407 IOSB
->Status
= STATUS_PENDING
;
410 Status
= NtDeviceIoControlFile((HANDLE
)Handle
,
421 /* Wait for completition of not overlapped */
422 if (Status
== STATUS_PENDING
&& lpOverlapped
== NULL
) {
423 WaitForSingleObject(SockEvent
, 0); // BUGBUG, shouldn wait infintely for send...
424 Status
= IOSB
->Status
;
427 NtClose( SockEvent
);
429 if (Status
== STATUS_PENDING
) {
430 AFD_DbgPrint(MID_TRACE
,("Leaving (Pending)\n"));
431 return WSA_IO_PENDING
;
434 /* Return Number of bytes Sent */
435 *lpNumberOfBytesSent
= (DWORD
)IOSB
->Information
;
437 AFD_DbgPrint(MID_TRACE
,("Leaving (Success, %d)\n", IOSB
->Information
));
440 return STATUS_SUCCESS
;
449 LPDWORD lpNumberOfBytesSent
,
451 struct sockaddr
*SocketAddress
,
452 int SocketAddressLength
,
453 LPWSAOVERLAPPED lpOverlapped
,
454 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
,
455 LPWSATHREADID lpThreadId
,
458 PIO_STATUS_BLOCK IOSB
;
459 IO_STATUS_BLOCK DummyIOSB
;
460 AFD_SEND_INFO_UDP SendInfo
;
465 PTRANSPORT_ADDRESS RemoteAddress
;
466 UCHAR TdiBuffer
[0x16];
467 PSOCKADDR BindAddress
;
468 INT BindAddressLength
;
470 PSOCKET_INFORMATION Socket
;
473 /* Get the Socket Structure associate to this Socket*/
474 Socket
= GetSocketStructure(Handle
);
476 Status
= NtCreateEvent( &SockEvent
, GENERIC_READ
| GENERIC_WRITE
,
479 if( !NT_SUCCESS(Status
) ) return -1;
482 if (Socket
->SharedData
.State
== SocketOpen
) {
484 /* Get the Wildcard Address */
485 BindAddressLength
= Socket
->HelperData
->MaxWSAddressLength
;
486 BindAddress
= HeapAlloc(GlobalHeap
, 0, BindAddressLength
);
487 Socket
->HelperData
->WSHGetWildcardSockaddr (Socket
->HelperContext
,
492 WSPBind(Handle
, BindAddress
, BindAddressLength
, NULL
);
495 /* Set up Address in TDI Format */
496 RemoteAddress
= (PTRANSPORT_ADDRESS
)TdiBuffer
;
497 RemoteAddress
->TAAddressCount
= 1;
498 RemoteAddress
->Address
[0].AddressLength
= SocketAddressLength
- sizeof(SocketAddress
->sa_family
);
499 RtlCopyMemory(&RemoteAddress
->Address
[0].AddressType
, SocketAddress
, SocketAddressLength
);
501 /* Set up Structure */
502 SendInfo
.BufferArray
= (PAFD_WSABUF
)lpBuffers
;
503 SendInfo
.AfdFlags
= Socket
->SharedData
.NonBlocking
? AFD_IMMEDIATE
: 0;
504 SendInfo
.BufferCount
= dwBufferCount
;
505 SendInfo
.RemoteAddress
= RemoteAddress
;
506 SendInfo
.SizeOfRemoteAddress
= Socket
->HelperData
->MaxTDIAddressLength
;
508 /* Verifiy if we should use APC */
509 if (lpOverlapped
== NULL
) {
511 /* Not using Overlapped structure, so use normal blocking on event */
519 if (lpCompletionRoutine
== NULL
) {
521 /* Using Overlapped Structure, but no Completition Routine, so no need for APC */
522 APCContext
= lpOverlapped
;
524 Event
= lpOverlapped
->hEvent
;
528 /* Using Overlapped Structure and a Completition Routine, so use an APC */
529 APCFunction
= NULL
; // should be a private io completition function inside us
530 APCContext
= lpCompletionRoutine
;
531 SendInfo
.AfdFlags
= AFD_SKIP_FIO
;
534 IOSB
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
535 SendInfo
.AfdFlags
|= AFD_OVERLAPPED
;
539 Status
= NtDeviceIoControlFile((HANDLE
)Handle
,
544 IOCTL_AFD_SEND_DATAGRAM
,
550 /* Wait for completition of not overlapped */
551 if (Status
== STATUS_PENDING
&& lpOverlapped
== NULL
) {
552 WaitForSingleObject(SockEvent
, 0); // BUGBUG, shouldn wait infintely for send...
553 Status
= IOSB
->Status
;
556 NtClose( SockEvent
);
558 if (Status
== STATUS_PENDING
) {
559 return WSA_IO_PENDING
;
562 /* Return Number of bytes Sent */
563 *lpNumberOfBytesSent
= (DWORD
)IOSB
->Information
;
566 return STATUS_SUCCESS
;
572 OUT LPWSABUF lpInboundDisconnectData
,
586 IN LPWSABUF lpOutboundDisconnectData
,