2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/net/afd/afd/connect.c
5 * PURPOSE: Ancillary functions driver
6 * PROGRAMMER: Art Yerkes (ayerkes@speakeasy.net)
15 AfdGetConnectOptions(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
16 PIO_STACK_LOCATION IrpSp
)
18 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
19 PAFD_FCB FCB
= FileObject
->FsContext
;
20 UINT BufferSize
= IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
;
22 UNREFERENCED_PARAMETER(DeviceObject
);
24 if (!SocketAcquireStateLock(FCB
)) return LostSocket(Irp
);
26 if (FCB
->ConnectOptionsSize
== 0)
28 AFD_DbgPrint(MIN_TRACE
,("Invalid parameter\n"));
29 return UnlockAndMaybeComplete(FCB
, STATUS_INVALID_PARAMETER
, Irp
, 0);
32 ASSERT(FCB
->ConnectOptions
);
34 if (FCB
->FilledConnectOptions
< BufferSize
) BufferSize
= FCB
->FilledConnectOptions
;
36 RtlCopyMemory(Irp
->UserBuffer
,
40 return UnlockAndMaybeComplete(FCB
, STATUS_SUCCESS
, Irp
, BufferSize
);
45 AfdSetConnectOptions(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
46 PIO_STACK_LOCATION IrpSp
)
48 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
49 PAFD_FCB FCB
= FileObject
->FsContext
;
50 PVOID ConnectOptions
= LockRequest(Irp
, IrpSp
, FALSE
, NULL
);
51 UINT ConnectOptionsSize
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
53 UNREFERENCED_PARAMETER(DeviceObject
);
55 if (!SocketAcquireStateLock(FCB
)) return LostSocket(Irp
);
58 return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
60 if (FCB
->ConnectOptions
)
62 ExFreePoolWithTag(FCB
->ConnectOptions
, TAG_AFD_CONNECT_OPTIONS
);
63 FCB
->ConnectOptions
= NULL
;
64 FCB
->ConnectOptionsSize
= 0;
65 FCB
->FilledConnectOptions
= 0;
68 FCB
->ConnectOptions
= ExAllocatePoolWithTag(PagedPool
,
70 TAG_AFD_CONNECT_OPTIONS
);
72 if (!FCB
->ConnectOptions
)
73 return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
75 RtlCopyMemory(FCB
->ConnectOptions
,
79 FCB
->ConnectOptionsSize
= ConnectOptionsSize
;
81 return UnlockAndMaybeComplete(FCB
, STATUS_SUCCESS
, Irp
, 0);
86 AfdSetConnectOptionsSize(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
87 PIO_STACK_LOCATION IrpSp
)
89 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
90 PAFD_FCB FCB
= FileObject
->FsContext
;
91 PUINT ConnectOptionsSize
= LockRequest(Irp
, IrpSp
, FALSE
, NULL
);
92 UINT BufferSize
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
94 UNREFERENCED_PARAMETER(DeviceObject
);
96 if (!SocketAcquireStateLock(FCB
)) return LostSocket(Irp
);
98 if (!ConnectOptionsSize
)
99 return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
101 if (BufferSize
< sizeof(UINT
))
103 AFD_DbgPrint(MIN_TRACE
,("Buffer too small\n"));
104 return UnlockAndMaybeComplete(FCB
, STATUS_BUFFER_TOO_SMALL
, Irp
, 0);
107 if (FCB
->ConnectOptions
)
109 ExFreePoolWithTag(FCB
->ConnectOptions
, TAG_AFD_CONNECT_OPTIONS
);
110 FCB
->ConnectOptionsSize
= 0;
111 FCB
->FilledConnectOptions
= 0;
114 FCB
->ConnectOptions
= ExAllocatePoolWithTag(PagedPool
,
116 TAG_AFD_CONNECT_OPTIONS
);
118 if (!FCB
->ConnectOptions
) return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
120 FCB
->ConnectOptionsSize
= *ConnectOptionsSize
;
122 return UnlockAndMaybeComplete(FCB
, STATUS_SUCCESS
, Irp
, 0);
127 AfdGetConnectData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
128 PIO_STACK_LOCATION IrpSp
)
130 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
131 PAFD_FCB FCB
= FileObject
->FsContext
;
132 UINT BufferSize
= IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
;
134 UNREFERENCED_PARAMETER(DeviceObject
);
136 if (!SocketAcquireStateLock(FCB
)) return LostSocket(Irp
);
138 if (FCB
->ConnectDataSize
== 0)
140 AFD_DbgPrint(MIN_TRACE
,("Invalid parameter\n"));
141 return UnlockAndMaybeComplete(FCB
, STATUS_INVALID_PARAMETER
, Irp
, 0);
144 ASSERT(FCB
->ConnectData
);
146 if (FCB
->FilledConnectData
< BufferSize
) BufferSize
= FCB
->FilledConnectData
;
148 RtlCopyMemory(Irp
->UserBuffer
,
152 return UnlockAndMaybeComplete(FCB
, STATUS_SUCCESS
, Irp
, BufferSize
);
157 AfdSetConnectData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
158 PIO_STACK_LOCATION IrpSp
)
160 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
161 PAFD_FCB FCB
= FileObject
->FsContext
;
162 PVOID ConnectData
= LockRequest(Irp
, IrpSp
, FALSE
, NULL
);
163 UINT ConnectDataSize
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
165 UNREFERENCED_PARAMETER(DeviceObject
);
167 if (!SocketAcquireStateLock(FCB
)) return LostSocket(Irp
);
170 return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
172 if (FCB
->ConnectData
)
174 ExFreePoolWithTag(FCB
->ConnectData
, TAG_AFD_CONNECT_DATA
);
175 FCB
->ConnectData
= NULL
;
176 FCB
->ConnectDataSize
= 0;
177 FCB
->FilledConnectData
= 0;
180 FCB
->ConnectData
= ExAllocatePoolWithTag(PagedPool
,
182 TAG_AFD_CONNECT_DATA
);
184 if (!FCB
->ConnectData
) return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
186 RtlCopyMemory(FCB
->ConnectData
,
190 FCB
->ConnectDataSize
= ConnectDataSize
;
192 return UnlockAndMaybeComplete(FCB
, STATUS_SUCCESS
, Irp
, 0);
197 AfdSetConnectDataSize(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
198 PIO_STACK_LOCATION IrpSp
)
200 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
201 PAFD_FCB FCB
= FileObject
->FsContext
;
202 PUINT ConnectDataSize
= LockRequest(Irp
, IrpSp
, FALSE
, NULL
);
203 UINT BufferSize
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
205 UNREFERENCED_PARAMETER(DeviceObject
);
207 if (!SocketAcquireStateLock(FCB
)) return LostSocket(Irp
);
209 if (!ConnectDataSize
)
210 return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
212 if (BufferSize
< sizeof(UINT
))
214 AFD_DbgPrint(MIN_TRACE
,("Buffer too small\n"));
215 return UnlockAndMaybeComplete(FCB
, STATUS_BUFFER_TOO_SMALL
, Irp
, 0);
218 if (FCB
->ConnectData
)
220 ExFreePoolWithTag(FCB
->ConnectData
, TAG_AFD_CONNECT_DATA
);
221 FCB
->ConnectDataSize
= 0;
222 FCB
->FilledConnectData
= 0;
225 FCB
->ConnectData
= ExAllocatePoolWithTag(PagedPool
,
227 TAG_AFD_CONNECT_DATA
);
229 if (!FCB
->ConnectData
) return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
231 FCB
->ConnectDataSize
= *ConnectDataSize
;
233 return UnlockAndMaybeComplete(FCB
, STATUS_SUCCESS
, Irp
, 0);
238 WarmSocketForConnection(PAFD_FCB FCB
) {
241 if( !FCB
->TdiDeviceName
.Length
|| !FCB
->TdiDeviceName
.Buffer
) {
242 AFD_DbgPrint(MIN_TRACE
,("Null Device\n"));
243 return STATUS_NO_SUCH_DEVICE
;
246 Status
= TdiOpenConnectionEndpointFile(&FCB
->TdiDeviceName
,
247 &FCB
->Connection
.Handle
,
248 &FCB
->Connection
.Object
);
250 if( NT_SUCCESS(Status
) ) {
251 Status
= TdiAssociateAddressFile( FCB
->AddressFile
.Handle
,
252 FCB
->Connection
.Object
);
259 MakeSocketIntoConnection(PAFD_FCB FCB
) {
262 ASSERT(!FCB
->Recv
.Window
);
263 ASSERT(!FCB
->Send
.Window
);
267 Status
= TdiQueryMaxDatagramLength(FCB
->Connection
.Object
,
269 if (!NT_SUCCESS(Status
))
275 Status
= TdiQueryMaxDatagramLength(FCB
->Connection
.Object
,
277 if (!NT_SUCCESS(Status
))
281 /* Allocate the receive area and start receiving */
282 if (!FCB
->Recv
.Window
)
284 FCB
->Recv
.Window
= ExAllocatePoolWithTag(PagedPool
,
286 TAG_AFD_DATA_BUFFER
);
288 if( !FCB
->Recv
.Window
) return STATUS_NO_MEMORY
;
291 if (!FCB
->Send
.Window
)
293 FCB
->Send
.Window
= ExAllocatePoolWithTag(PagedPool
,
295 TAG_AFD_DATA_BUFFER
);
297 if( !FCB
->Send
.Window
) return STATUS_NO_MEMORY
;
300 FCB
->State
= SOCKET_STATE_CONNECTED
;
302 Status
= TdiReceive( &FCB
->ReceiveIrp
.InFlightRequest
,
303 FCB
->Connection
.Object
,
310 if( Status
== STATUS_PENDING
) Status
= STATUS_SUCCESS
;
312 FCB
->PollState
|= AFD_EVENT_CONNECT
| AFD_EVENT_SEND
;
313 FCB
->PollStatus
[FD_CONNECT_BIT
] = STATUS_SUCCESS
;
314 FCB
->PollStatus
[FD_WRITE_BIT
] = STATUS_SUCCESS
;
315 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
320 static IO_COMPLETION_ROUTINE StreamSocketConnectComplete
;
324 StreamSocketConnectComplete(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
326 NTSTATUS Status
= Irp
->IoStatus
.Status
;
327 PAFD_FCB FCB
= (PAFD_FCB
)Context
;
328 PLIST_ENTRY NextIrpEntry
;
331 AFD_DbgPrint(MID_TRACE
,("Called: FCB %p, FO %p\n",
332 Context
, FCB
->FileObject
));
334 /* I was wrong about this before as we can have pending writes to a not
335 * yet connected socket */
336 if( !SocketAcquireStateLock( FCB
) )
337 return STATUS_FILE_CLOSED
;
339 AFD_DbgPrint(MID_TRACE
,("Irp->IoStatus.Status = %x\n",
340 Irp
->IoStatus
.Status
));
342 ASSERT(FCB
->ConnectIrp
.InFlightRequest
== Irp
);
343 FCB
->ConnectIrp
.InFlightRequest
= NULL
;
345 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
346 /* Cleanup our IRP queue because the FCB is being destroyed */
347 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_CONNECT
] ) ) {
348 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_CONNECT
]);
349 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
350 NextIrp
->IoStatus
.Status
= STATUS_FILE_CLOSED
;
351 NextIrp
->IoStatus
.Information
= 0;
352 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
353 (void)IoSetCancelRoutine(NextIrp
, NULL
);
354 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
356 SocketStateUnlock( FCB
);
357 return STATUS_FILE_CLOSED
;
360 if( !NT_SUCCESS(Irp
->IoStatus
.Status
) ) {
361 FCB
->PollState
|= AFD_EVENT_CONNECT_FAIL
;
362 FCB
->PollStatus
[FD_CONNECT_BIT
] = Irp
->IoStatus
.Status
;
363 AFD_DbgPrint(MID_TRACE
,("Going to bound state\n"));
364 FCB
->State
= SOCKET_STATE_BOUND
;
365 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
368 /* Succeed pending irps on the FUNCTION_CONNECT list */
369 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_CONNECT
] ) ) {
370 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_CONNECT
]);
371 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
372 AFD_DbgPrint(MID_TRACE
,("Completing connect %p\n", NextIrp
));
373 NextIrp
->IoStatus
.Status
= Status
;
374 NextIrp
->IoStatus
.Information
= NT_SUCCESS(Status
) ? ((ULONG_PTR
)FCB
->Connection
.Handle
) : 0;
375 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
376 (void)IoSetCancelRoutine(NextIrp
, NULL
);
377 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
380 if( NT_SUCCESS(Status
) ) {
381 Status
= MakeSocketIntoConnection( FCB
);
383 if( !NT_SUCCESS(Status
) ) {
384 SocketStateUnlock( FCB
);
388 FCB
->FilledConnectData
= MIN(FCB
->ConnectReturnInfo
->UserDataLength
, FCB
->ConnectDataSize
);
389 if (FCB
->FilledConnectData
)
391 RtlCopyMemory(FCB
->ConnectData
,
392 FCB
->ConnectReturnInfo
->UserData
,
393 FCB
->FilledConnectData
);
396 FCB
->FilledConnectOptions
= MIN(FCB
->ConnectReturnInfo
->OptionsLength
, FCB
->ConnectOptionsSize
);
397 if (FCB
->FilledConnectOptions
)
399 RtlCopyMemory(FCB
->ConnectOptions
,
400 FCB
->ConnectReturnInfo
->Options
,
401 FCB
->FilledConnectOptions
);
404 if( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_SEND
] ) ) {
405 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
]);
406 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
,
407 Tail
.Overlay
.ListEntry
);
408 AFD_DbgPrint(MID_TRACE
,("Launching send request %p\n", NextIrp
));
409 Status
= AfdConnectedSocketWriteData
412 IoGetCurrentIrpStackLocation( NextIrp
),
416 if( Status
== STATUS_PENDING
)
417 Status
= STATUS_SUCCESS
;
420 SocketStateUnlock( FCB
);
422 AFD_DbgPrint(MID_TRACE
,("Returning %x\n", Status
));
427 /* Return the socket object for ths request only if it is a connected or
431 AfdStreamSocketConnect(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
432 PIO_STACK_LOCATION IrpSp
) {
433 NTSTATUS Status
= STATUS_INVALID_PARAMETER
;
434 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
435 PAFD_FCB FCB
= FileObject
->FsContext
;
436 PAFD_CONNECT_INFO ConnectReq
;
437 AFD_DbgPrint(MID_TRACE
,("Called on %p\n", FCB
));
439 UNREFERENCED_PARAMETER(DeviceObject
);
441 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
442 if( !(ConnectReq
= LockRequest( Irp
, IrpSp
, FALSE
, NULL
)) )
443 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
, Irp
,
446 AFD_DbgPrint(MID_TRACE
,("Connect request:\n"));
450 IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
);
453 if( FCB
->Flags
& AFD_ENDPOINT_CONNECTIONLESS
)
455 if (FCB
->RemoteAddress
)
457 ExFreePoolWithTag(FCB
->RemoteAddress
, TAG_AFD_TRANSPORT_ADDRESS
);
461 TaCopyTransportAddress( &ConnectReq
->RemoteAddress
);
463 if( !FCB
->RemoteAddress
)
464 Status
= STATUS_NO_MEMORY
;
466 Status
= STATUS_SUCCESS
;
468 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
471 switch( FCB
->State
) {
472 case SOCKET_STATE_CONNECTED
:
473 Status
= STATUS_SUCCESS
;
476 case SOCKET_STATE_CONNECTING
:
477 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_CONNECT
);
479 case SOCKET_STATE_CREATED
:
480 if (FCB
->LocalAddress
)
482 ExFreePoolWithTag(FCB
->LocalAddress
, TAG_AFD_TRANSPORT_ADDRESS
);
486 TaBuildNullTransportAddress( ConnectReq
->RemoteAddress
.Address
[0].AddressType
);
488 if( FCB
->LocalAddress
) {
489 Status
= WarmSocketForBind( FCB
, AFD_SHARE_WILDCARD
);
491 if( NT_SUCCESS(Status
) )
492 FCB
->State
= SOCKET_STATE_BOUND
;
494 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
496 return UnlockAndMaybeComplete
497 ( FCB
, STATUS_NO_MEMORY
, Irp
, 0 );
499 /* Drop through to SOCKET_STATE_BOUND */
501 case SOCKET_STATE_BOUND
:
502 if (FCB
->RemoteAddress
)
504 ExFreePoolWithTag(FCB
->RemoteAddress
, TAG_AFD_TRANSPORT_ADDRESS
);
508 TaCopyTransportAddress( &ConnectReq
->RemoteAddress
);
510 if( !FCB
->RemoteAddress
) {
511 Status
= STATUS_NO_MEMORY
;
515 Status
= WarmSocketForConnection( FCB
);
517 if( !NT_SUCCESS(Status
) )
520 if (FCB
->ConnectReturnInfo
)
522 ExFreePoolWithTag(FCB
->ConnectReturnInfo
, TAG_AFD_TDI_CONNECTION_INFORMATION
);
525 Status
= TdiBuildConnectionInfo
526 ( &FCB
->ConnectReturnInfo
,
527 &ConnectReq
->RemoteAddress
);
529 if( NT_SUCCESS(Status
) )
531 if (FCB
->ConnectCallInfo
)
533 ExFreePoolWithTag(FCB
->ConnectCallInfo
, TAG_AFD_TDI_CONNECTION_INFORMATION
);
536 Status
= TdiBuildConnectionInfo(&FCB
->ConnectCallInfo
,
537 &ConnectReq
->RemoteAddress
);
542 if( NT_SUCCESS(Status
) ) {
543 FCB
->ConnectCallInfo
->UserData
= FCB
->ConnectData
;
544 FCB
->ConnectCallInfo
->UserDataLength
= FCB
->ConnectDataSize
;
545 FCB
->ConnectCallInfo
->Options
= FCB
->ConnectOptions
;
546 FCB
->ConnectCallInfo
->OptionsLength
= FCB
->ConnectOptionsSize
;
548 FCB
->State
= SOCKET_STATE_CONNECTING
;
550 AFD_DbgPrint(MID_TRACE
,("Queueing IRP %p\n", Irp
));
551 Status
= QueueUserModeIrp( FCB
, Irp
, FUNCTION_CONNECT
);
552 if (Status
== STATUS_PENDING
)
554 Status
= TdiConnect( &FCB
->ConnectIrp
.InFlightRequest
,
555 FCB
->Connection
.Object
,
556 FCB
->ConnectCallInfo
,
557 FCB
->ConnectReturnInfo
,
558 StreamSocketConnectComplete
,
562 if (Status
!= STATUS_PENDING
)
563 FCB
->State
= SOCKET_STATE_BOUND
;
565 SocketStateUnlock(FCB
);
572 AFD_DbgPrint(MIN_TRACE
,("Inappropriate socket state %u for connect\n",
577 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );