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)
14 AfdGetConnectOptions(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
15 PIO_STACK_LOCATION IrpSp
)
17 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
18 PAFD_FCB FCB
= FileObject
->FsContext
;
19 UINT BufferSize
= IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
;
21 if (!SocketAcquireStateLock(FCB
)) return LostSocket(Irp
);
23 if (FCB
->ConnectOptionsSize
== 0)
25 AFD_DbgPrint(MIN_TRACE
,("Invalid parameter\n"));
26 return UnlockAndMaybeComplete(FCB
, STATUS_INVALID_PARAMETER
, Irp
, 0);
29 ASSERT(FCB
->ConnectOptions
);
31 if (FCB
->FilledConnectOptions
< BufferSize
) BufferSize
= FCB
->FilledConnectOptions
;
33 RtlCopyMemory(Irp
->UserBuffer
,
37 return UnlockAndMaybeComplete(FCB
, STATUS_SUCCESS
, Irp
, BufferSize
);
42 AfdSetConnectOptions(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
43 PIO_STACK_LOCATION IrpSp
)
45 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
46 PAFD_FCB FCB
= FileObject
->FsContext
;
47 PVOID ConnectOptions
= LockRequest(Irp
, IrpSp
, FALSE
, NULL
);
48 UINT ConnectOptionsSize
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
50 if (!SocketAcquireStateLock(FCB
)) return LostSocket(Irp
);
53 return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
55 if (FCB
->ConnectOptions
)
57 ExFreePool(FCB
->ConnectOptions
);
58 FCB
->ConnectOptions
= NULL
;
59 FCB
->ConnectOptionsSize
= 0;
60 FCB
->FilledConnectOptions
= 0;
63 FCB
->ConnectOptions
= ExAllocatePool(PagedPool
, ConnectOptionsSize
);
64 if (!FCB
->ConnectOptions
)
65 return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
67 RtlCopyMemory(FCB
->ConnectOptions
,
71 FCB
->ConnectOptionsSize
= ConnectOptionsSize
;
73 return UnlockAndMaybeComplete(FCB
, STATUS_SUCCESS
, Irp
, 0);
78 AfdSetConnectOptionsSize(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
79 PIO_STACK_LOCATION IrpSp
)
81 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
82 PAFD_FCB FCB
= FileObject
->FsContext
;
83 PUINT ConnectOptionsSize
= LockRequest(Irp
, IrpSp
, FALSE
, NULL
);
84 UINT BufferSize
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
86 if (!SocketAcquireStateLock(FCB
)) return LostSocket(Irp
);
88 if (!ConnectOptionsSize
)
89 return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
91 if (BufferSize
< sizeof(UINT
))
93 AFD_DbgPrint(MIN_TRACE
,("Buffer too small\n"));
94 return UnlockAndMaybeComplete(FCB
, STATUS_BUFFER_TOO_SMALL
, Irp
, 0);
97 if (FCB
->ConnectOptions
)
99 ExFreePool(FCB
->ConnectOptions
);
100 FCB
->ConnectOptionsSize
= 0;
101 FCB
->FilledConnectOptions
= 0;
104 FCB
->ConnectOptions
= ExAllocatePool(PagedPool
, *ConnectOptionsSize
);
105 if (!FCB
->ConnectOptions
) return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
107 FCB
->ConnectOptionsSize
= *ConnectOptionsSize
;
109 return UnlockAndMaybeComplete(FCB
, STATUS_SUCCESS
, Irp
, 0);
114 AfdGetConnectData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
115 PIO_STACK_LOCATION IrpSp
)
117 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
118 PAFD_FCB FCB
= FileObject
->FsContext
;
119 UINT BufferSize
= IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
;
121 if (!SocketAcquireStateLock(FCB
)) return LostSocket(Irp
);
123 if (FCB
->ConnectDataSize
== 0)
125 AFD_DbgPrint(MIN_TRACE
,("Invalid parameter\n"));
126 return UnlockAndMaybeComplete(FCB
, STATUS_INVALID_PARAMETER
, Irp
, 0);
129 ASSERT(FCB
->ConnectData
);
131 if (FCB
->FilledConnectData
< BufferSize
) BufferSize
= FCB
->FilledConnectData
;
133 RtlCopyMemory(Irp
->UserBuffer
,
137 return UnlockAndMaybeComplete(FCB
, STATUS_SUCCESS
, Irp
, BufferSize
);
142 AfdSetConnectData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
143 PIO_STACK_LOCATION IrpSp
)
145 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
146 PAFD_FCB FCB
= FileObject
->FsContext
;
147 PVOID ConnectData
= LockRequest(Irp
, IrpSp
, FALSE
, NULL
);
148 UINT ConnectDataSize
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
150 if (!SocketAcquireStateLock(FCB
)) return LostSocket(Irp
);
153 return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
155 if (FCB
->ConnectData
)
157 ExFreePool(FCB
->ConnectData
);
158 FCB
->ConnectData
= NULL
;
159 FCB
->ConnectDataSize
= 0;
160 FCB
->FilledConnectData
= 0;
163 FCB
->ConnectData
= ExAllocatePool(PagedPool
, ConnectDataSize
);
164 if (!FCB
->ConnectData
) return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
166 RtlCopyMemory(FCB
->ConnectData
,
170 FCB
->ConnectDataSize
= ConnectDataSize
;
172 return UnlockAndMaybeComplete(FCB
, STATUS_SUCCESS
, Irp
, 0);
177 AfdSetConnectDataSize(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
178 PIO_STACK_LOCATION IrpSp
)
180 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
181 PAFD_FCB FCB
= FileObject
->FsContext
;
182 PUINT ConnectDataSize
= LockRequest(Irp
, IrpSp
, FALSE
, NULL
);
183 UINT BufferSize
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
185 if (!SocketAcquireStateLock(FCB
)) return LostSocket(Irp
);
187 if (!ConnectDataSize
)
188 return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
190 if (BufferSize
< sizeof(UINT
))
192 AFD_DbgPrint(MIN_TRACE
,("Buffer too small\n"));
193 return UnlockAndMaybeComplete(FCB
, STATUS_BUFFER_TOO_SMALL
, Irp
, 0);
196 if (FCB
->ConnectData
)
198 ExFreePool(FCB
->ConnectData
);
199 FCB
->ConnectDataSize
= 0;
200 FCB
->FilledConnectData
= 0;
203 FCB
->ConnectData
= ExAllocatePool(PagedPool
, *ConnectDataSize
);
204 if (!FCB
->ConnectData
) return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
206 FCB
->ConnectDataSize
= *ConnectDataSize
;
208 return UnlockAndMaybeComplete(FCB
, STATUS_SUCCESS
, Irp
, 0);
213 WarmSocketForConnection(PAFD_FCB FCB
) {
216 if( !FCB
->TdiDeviceName
.Length
|| !FCB
->TdiDeviceName
.Buffer
) {
217 AFD_DbgPrint(MIN_TRACE
,("Null Device\n"));
218 return STATUS_NO_SUCH_DEVICE
;
221 Status
= TdiOpenConnectionEndpointFile(&FCB
->TdiDeviceName
,
222 &FCB
->Connection
.Handle
,
223 &FCB
->Connection
.Object
);
225 if( NT_SUCCESS(Status
) ) {
226 Status
= TdiAssociateAddressFile( FCB
->AddressFile
.Handle
,
227 FCB
->Connection
.Object
);
234 MakeSocketIntoConnection(PAFD_FCB FCB
) {
237 ASSERT(!FCB
->Recv
.Window
);
238 ASSERT(!FCB
->Send
.Window
);
242 Status
= TdiQueryMaxDatagramLength(FCB
->Connection
.Object
,
244 if (!NT_SUCCESS(Status
))
250 Status
= TdiQueryMaxDatagramLength(FCB
->Connection
.Object
,
252 if (!NT_SUCCESS(Status
))
256 /* Allocate the receive area and start receiving */
257 if (!FCB
->Recv
.Window
)
259 FCB
->Recv
.Window
= ExAllocatePool( PagedPool
, FCB
->Recv
.Size
);
260 if( !FCB
->Recv
.Window
) return STATUS_NO_MEMORY
;
263 if (!FCB
->Send
.Window
)
265 FCB
->Send
.Window
= ExAllocatePool( PagedPool
, FCB
->Send
.Size
);
266 if( !FCB
->Send
.Window
) return STATUS_NO_MEMORY
;
269 FCB
->State
= SOCKET_STATE_CONNECTED
;
271 Status
= TdiReceive( &FCB
->ReceiveIrp
.InFlightRequest
,
272 FCB
->Connection
.Object
,
276 &FCB
->ReceiveIrp
.Iosb
,
280 if( Status
== STATUS_PENDING
) Status
= STATUS_SUCCESS
;
282 FCB
->PollState
|= AFD_EVENT_CONNECT
| AFD_EVENT_SEND
;
283 FCB
->PollStatus
[FD_CONNECT_BIT
] = STATUS_SUCCESS
;
284 FCB
->PollStatus
[FD_WRITE_BIT
] = STATUS_SUCCESS
;
285 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
293 StreamSocketConnectComplete(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
295 NTSTATUS Status
= Irp
->IoStatus
.Status
;
296 PAFD_FCB FCB
= (PAFD_FCB
)Context
;
297 PLIST_ENTRY NextIrpEntry
;
300 AFD_DbgPrint(MID_TRACE
,("Called: FCB %x, FO %x\n",
301 Context
, FCB
->FileObject
));
303 /* I was wrong about this before as we can have pending writes to a not
304 * yet connected socket */
305 if( !SocketAcquireStateLock( FCB
) )
306 return STATUS_FILE_CLOSED
;
308 AFD_DbgPrint(MID_TRACE
,("Irp->IoStatus.Status = %x\n",
309 Irp
->IoStatus
.Status
));
311 ASSERT(FCB
->ConnectIrp
.InFlightRequest
== Irp
);
312 FCB
->ConnectIrp
.InFlightRequest
= NULL
;
314 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
315 /* Cleanup our IRP queue because the FCB is being destroyed */
316 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_CONNECT
] ) ) {
317 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_CONNECT
]);
318 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
319 NextIrp
->IoStatus
.Status
= STATUS_FILE_CLOSED
;
320 NextIrp
->IoStatus
.Information
= 0;
321 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
322 (void)IoSetCancelRoutine(NextIrp
, NULL
);
323 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
325 SocketStateUnlock( FCB
);
326 return STATUS_FILE_CLOSED
;
329 if( !NT_SUCCESS(Irp
->IoStatus
.Status
) ) {
330 FCB
->PollState
|= AFD_EVENT_CONNECT_FAIL
;
331 FCB
->PollStatus
[FD_CONNECT_BIT
] = Irp
->IoStatus
.Status
;
332 AFD_DbgPrint(MID_TRACE
,("Going to bound state\n"));
333 FCB
->State
= SOCKET_STATE_BOUND
;
334 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
337 /* Succeed pending irps on the FUNCTION_CONNECT list */
338 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_CONNECT
] ) ) {
339 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_CONNECT
]);
340 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
341 AFD_DbgPrint(MID_TRACE
,("Completing connect %x\n", NextIrp
));
342 NextIrp
->IoStatus
.Status
= Status
;
343 NextIrp
->IoStatus
.Information
= NT_SUCCESS(Status
) ? ((ULONG_PTR
)FCB
->Connection
.Handle
) : 0;
344 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
345 (void)IoSetCancelRoutine(NextIrp
, NULL
);
346 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
349 if( NT_SUCCESS(Status
) ) {
350 Status
= MakeSocketIntoConnection( FCB
);
352 if( !NT_SUCCESS(Status
) ) {
353 SocketStateUnlock( FCB
);
357 FCB
->FilledConnectData
= MIN(FCB
->ConnectReturnInfo
->UserDataLength
, FCB
->ConnectDataSize
);
358 if (FCB
->FilledConnectData
)
360 RtlCopyMemory(FCB
->ConnectData
,
361 FCB
->ConnectReturnInfo
->UserData
,
362 FCB
->FilledConnectData
);
365 FCB
->FilledConnectOptions
= MIN(FCB
->ConnectReturnInfo
->OptionsLength
, FCB
->ConnectOptionsSize
);
366 if (FCB
->FilledConnectOptions
)
368 RtlCopyMemory(FCB
->ConnectOptions
,
369 FCB
->ConnectReturnInfo
->Options
,
370 FCB
->FilledConnectOptions
);
373 if( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_SEND
] ) ) {
374 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
]);
375 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
,
376 Tail
.Overlay
.ListEntry
);
377 AFD_DbgPrint(MID_TRACE
,("Launching send request %x\n", NextIrp
));
378 Status
= AfdConnectedSocketWriteData
381 IoGetCurrentIrpStackLocation( NextIrp
),
385 if( Status
== STATUS_PENDING
)
386 Status
= STATUS_SUCCESS
;
389 SocketStateUnlock( FCB
);
391 AFD_DbgPrint(MID_TRACE
,("Returning %x\n", Status
));
396 /* Return the socket object for ths request only if it is a connected or
400 AfdStreamSocketConnect(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
401 PIO_STACK_LOCATION IrpSp
) {
402 NTSTATUS Status
= STATUS_INVALID_PARAMETER
;
403 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
404 PAFD_FCB FCB
= FileObject
->FsContext
;
405 PAFD_CONNECT_INFO ConnectReq
;
406 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
408 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
409 if( !(ConnectReq
= LockRequest( Irp
, IrpSp
, FALSE
, NULL
)) )
410 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
, Irp
,
413 AFD_DbgPrint(MID_TRACE
,("Connect request:\n"));
417 IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
);
420 if( FCB
->Flags
& AFD_ENDPOINT_CONNECTIONLESS
)
422 if( FCB
->RemoteAddress
) ExFreePool( FCB
->RemoteAddress
);
424 TaCopyTransportAddress( &ConnectReq
->RemoteAddress
);
426 if( !FCB
->RemoteAddress
)
427 Status
= STATUS_NO_MEMORY
;
429 Status
= STATUS_SUCCESS
;
431 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
434 switch( FCB
->State
) {
435 case SOCKET_STATE_CONNECTED
:
436 Status
= STATUS_SUCCESS
;
439 case SOCKET_STATE_CONNECTING
:
440 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_CONNECT
);
442 case SOCKET_STATE_CREATED
:
443 if( FCB
->LocalAddress
) ExFreePool( FCB
->LocalAddress
);
445 TaBuildNullTransportAddress( ConnectReq
->RemoteAddress
.Address
[0].AddressType
);
447 if( FCB
->LocalAddress
) {
448 Status
= WarmSocketForBind( FCB
, AFD_SHARE_WILDCARD
);
450 if( NT_SUCCESS(Status
) )
451 FCB
->State
= SOCKET_STATE_BOUND
;
453 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
455 return UnlockAndMaybeComplete
456 ( FCB
, STATUS_NO_MEMORY
, Irp
, 0 );
458 /* Drop through to SOCKET_STATE_BOUND */
460 case SOCKET_STATE_BOUND
:
461 if( FCB
->RemoteAddress
) ExFreePool( FCB
->RemoteAddress
);
463 TaCopyTransportAddress( &ConnectReq
->RemoteAddress
);
465 if( !FCB
->RemoteAddress
) {
466 Status
= STATUS_NO_MEMORY
;
470 Status
= WarmSocketForConnection( FCB
);
472 if( !NT_SUCCESS(Status
) )
475 if (FCB
->ConnectReturnInfo
) ExFreePool(FCB
->ConnectReturnInfo
);
476 Status
= TdiBuildConnectionInfo
477 ( &FCB
->ConnectReturnInfo
,
478 &ConnectReq
->RemoteAddress
);
480 if( NT_SUCCESS(Status
) )
482 if (FCB
->ConnectCallInfo
) ExFreePool(FCB
->ConnectCallInfo
);
483 Status
= TdiBuildConnectionInfo(&FCB
->ConnectCallInfo
,
484 &ConnectReq
->RemoteAddress
);
489 if( NT_SUCCESS(Status
) ) {
490 FCB
->ConnectCallInfo
->UserData
= FCB
->ConnectData
;
491 FCB
->ConnectCallInfo
->UserDataLength
= FCB
->ConnectDataSize
;
492 FCB
->ConnectCallInfo
->Options
= FCB
->ConnectOptions
;
493 FCB
->ConnectCallInfo
->OptionsLength
= FCB
->ConnectOptionsSize
;
495 FCB
->State
= SOCKET_STATE_CONNECTING
;
497 AFD_DbgPrint(MID_TRACE
,("Queueing IRP %x\n", Irp
));
498 Status
= QueueUserModeIrp( FCB
, Irp
, FUNCTION_CONNECT
);
499 if (Status
== STATUS_PENDING
)
501 Status
= TdiConnect( &FCB
->ConnectIrp
.InFlightRequest
,
502 FCB
->Connection
.Object
,
503 FCB
->ConnectCallInfo
,
504 FCB
->ConnectReturnInfo
,
505 &FCB
->ConnectIrp
.Iosb
,
506 StreamSocketConnectComplete
,
510 if (Status
!= STATUS_PENDING
)
511 FCB
->State
= SOCKET_STATE_BOUND
;
513 SocketStateUnlock(FCB
);
520 AFD_DbgPrint(MIN_TRACE
,("Inappropriate socket state %d for connect\n",
525 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );