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 ExFreePool(FCB
->ConnectOptions
);
63 FCB
->ConnectOptions
= NULL
;
64 FCB
->ConnectOptionsSize
= 0;
65 FCB
->FilledConnectOptions
= 0;
68 FCB
->ConnectOptions
= ExAllocatePool(PagedPool
, ConnectOptionsSize
);
69 if (!FCB
->ConnectOptions
)
70 return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
72 RtlCopyMemory(FCB
->ConnectOptions
,
76 FCB
->ConnectOptionsSize
= ConnectOptionsSize
;
78 return UnlockAndMaybeComplete(FCB
, STATUS_SUCCESS
, Irp
, 0);
83 AfdSetConnectOptionsSize(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
84 PIO_STACK_LOCATION IrpSp
)
86 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
87 PAFD_FCB FCB
= FileObject
->FsContext
;
88 PUINT ConnectOptionsSize
= LockRequest(Irp
, IrpSp
, FALSE
, NULL
);
89 UINT BufferSize
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
91 UNREFERENCED_PARAMETER(DeviceObject
);
93 if (!SocketAcquireStateLock(FCB
)) return LostSocket(Irp
);
95 if (!ConnectOptionsSize
)
96 return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
98 if (BufferSize
< sizeof(UINT
))
100 AFD_DbgPrint(MIN_TRACE
,("Buffer too small\n"));
101 return UnlockAndMaybeComplete(FCB
, STATUS_BUFFER_TOO_SMALL
, Irp
, 0);
104 if (FCB
->ConnectOptions
)
106 ExFreePool(FCB
->ConnectOptions
);
107 FCB
->ConnectOptionsSize
= 0;
108 FCB
->FilledConnectOptions
= 0;
111 FCB
->ConnectOptions
= ExAllocatePool(PagedPool
, *ConnectOptionsSize
);
112 if (!FCB
->ConnectOptions
) return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
114 FCB
->ConnectOptionsSize
= *ConnectOptionsSize
;
116 return UnlockAndMaybeComplete(FCB
, STATUS_SUCCESS
, Irp
, 0);
121 AfdGetConnectData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
122 PIO_STACK_LOCATION IrpSp
)
124 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
125 PAFD_FCB FCB
= FileObject
->FsContext
;
126 UINT BufferSize
= IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
;
128 UNREFERENCED_PARAMETER(DeviceObject
);
130 if (!SocketAcquireStateLock(FCB
)) return LostSocket(Irp
);
132 if (FCB
->ConnectDataSize
== 0)
134 AFD_DbgPrint(MIN_TRACE
,("Invalid parameter\n"));
135 return UnlockAndMaybeComplete(FCB
, STATUS_INVALID_PARAMETER
, Irp
, 0);
138 ASSERT(FCB
->ConnectData
);
140 if (FCB
->FilledConnectData
< BufferSize
) BufferSize
= FCB
->FilledConnectData
;
142 RtlCopyMemory(Irp
->UserBuffer
,
146 return UnlockAndMaybeComplete(FCB
, STATUS_SUCCESS
, Irp
, BufferSize
);
151 AfdSetConnectData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
152 PIO_STACK_LOCATION IrpSp
)
154 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
155 PAFD_FCB FCB
= FileObject
->FsContext
;
156 PVOID ConnectData
= LockRequest(Irp
, IrpSp
, FALSE
, NULL
);
157 UINT ConnectDataSize
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
159 UNREFERENCED_PARAMETER(DeviceObject
);
161 if (!SocketAcquireStateLock(FCB
)) return LostSocket(Irp
);
164 return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
166 if (FCB
->ConnectData
)
168 ExFreePool(FCB
->ConnectData
);
169 FCB
->ConnectData
= NULL
;
170 FCB
->ConnectDataSize
= 0;
171 FCB
->FilledConnectData
= 0;
174 FCB
->ConnectData
= ExAllocatePool(PagedPool
, ConnectDataSize
);
175 if (!FCB
->ConnectData
) return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
177 RtlCopyMemory(FCB
->ConnectData
,
181 FCB
->ConnectDataSize
= ConnectDataSize
;
183 return UnlockAndMaybeComplete(FCB
, STATUS_SUCCESS
, Irp
, 0);
188 AfdSetConnectDataSize(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
189 PIO_STACK_LOCATION IrpSp
)
191 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
192 PAFD_FCB FCB
= FileObject
->FsContext
;
193 PUINT ConnectDataSize
= LockRequest(Irp
, IrpSp
, FALSE
, NULL
);
194 UINT BufferSize
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
196 UNREFERENCED_PARAMETER(DeviceObject
);
198 if (!SocketAcquireStateLock(FCB
)) return LostSocket(Irp
);
200 if (!ConnectDataSize
)
201 return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
203 if (BufferSize
< sizeof(UINT
))
205 AFD_DbgPrint(MIN_TRACE
,("Buffer too small\n"));
206 return UnlockAndMaybeComplete(FCB
, STATUS_BUFFER_TOO_SMALL
, Irp
, 0);
209 if (FCB
->ConnectData
)
211 ExFreePool(FCB
->ConnectData
);
212 FCB
->ConnectDataSize
= 0;
213 FCB
->FilledConnectData
= 0;
216 FCB
->ConnectData
= ExAllocatePool(PagedPool
, *ConnectDataSize
);
217 if (!FCB
->ConnectData
) return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
219 FCB
->ConnectDataSize
= *ConnectDataSize
;
221 return UnlockAndMaybeComplete(FCB
, STATUS_SUCCESS
, Irp
, 0);
226 WarmSocketForConnection(PAFD_FCB FCB
) {
229 if( !FCB
->TdiDeviceName
.Length
|| !FCB
->TdiDeviceName
.Buffer
) {
230 AFD_DbgPrint(MIN_TRACE
,("Null Device\n"));
231 return STATUS_NO_SUCH_DEVICE
;
234 Status
= TdiOpenConnectionEndpointFile(&FCB
->TdiDeviceName
,
235 &FCB
->Connection
.Handle
,
236 &FCB
->Connection
.Object
);
238 if( NT_SUCCESS(Status
) ) {
239 Status
= TdiAssociateAddressFile( FCB
->AddressFile
.Handle
,
240 FCB
->Connection
.Object
);
247 MakeSocketIntoConnection(PAFD_FCB FCB
) {
250 ASSERT(!FCB
->Recv
.Window
);
251 ASSERT(!FCB
->Send
.Window
);
255 Status
= TdiQueryMaxDatagramLength(FCB
->Connection
.Object
,
257 if (!NT_SUCCESS(Status
))
263 Status
= TdiQueryMaxDatagramLength(FCB
->Connection
.Object
,
265 if (!NT_SUCCESS(Status
))
269 /* Allocate the receive area and start receiving */
270 if (!FCB
->Recv
.Window
)
272 FCB
->Recv
.Window
= ExAllocatePool( PagedPool
, FCB
->Recv
.Size
);
273 if( !FCB
->Recv
.Window
) return STATUS_NO_MEMORY
;
276 if (!FCB
->Send
.Window
)
278 FCB
->Send
.Window
= ExAllocatePool( PagedPool
, FCB
->Send
.Size
);
279 if( !FCB
->Send
.Window
) return STATUS_NO_MEMORY
;
282 FCB
->State
= SOCKET_STATE_CONNECTED
;
284 Status
= TdiReceive( &FCB
->ReceiveIrp
.InFlightRequest
,
285 FCB
->Connection
.Object
,
289 &FCB
->ReceiveIrp
.Iosb
,
293 if( Status
== STATUS_PENDING
) Status
= STATUS_SUCCESS
;
295 FCB
->PollState
|= AFD_EVENT_CONNECT
| AFD_EVENT_SEND
;
296 FCB
->PollStatus
[FD_CONNECT_BIT
] = STATUS_SUCCESS
;
297 FCB
->PollStatus
[FD_WRITE_BIT
] = STATUS_SUCCESS
;
298 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
303 static IO_COMPLETION_ROUTINE StreamSocketConnectComplete
;
307 StreamSocketConnectComplete(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
309 NTSTATUS Status
= Irp
->IoStatus
.Status
;
310 PAFD_FCB FCB
= (PAFD_FCB
)Context
;
311 PLIST_ENTRY NextIrpEntry
;
314 AFD_DbgPrint(MID_TRACE
,("Called: FCB %p, FO %p\n",
315 Context
, FCB
->FileObject
));
317 /* I was wrong about this before as we can have pending writes to a not
318 * yet connected socket */
319 if( !SocketAcquireStateLock( FCB
) )
320 return STATUS_FILE_CLOSED
;
322 AFD_DbgPrint(MID_TRACE
,("Irp->IoStatus.Status = %x\n",
323 Irp
->IoStatus
.Status
));
325 ASSERT(FCB
->ConnectIrp
.InFlightRequest
== Irp
);
326 FCB
->ConnectIrp
.InFlightRequest
= NULL
;
328 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
329 /* Cleanup our IRP queue because the FCB is being destroyed */
330 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_CONNECT
] ) ) {
331 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_CONNECT
]);
332 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
333 NextIrp
->IoStatus
.Status
= STATUS_FILE_CLOSED
;
334 NextIrp
->IoStatus
.Information
= 0;
335 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
336 (void)IoSetCancelRoutine(NextIrp
, NULL
);
337 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
339 SocketStateUnlock( FCB
);
340 return STATUS_FILE_CLOSED
;
343 if( !NT_SUCCESS(Irp
->IoStatus
.Status
) ) {
344 FCB
->PollState
|= AFD_EVENT_CONNECT_FAIL
;
345 FCB
->PollStatus
[FD_CONNECT_BIT
] = Irp
->IoStatus
.Status
;
346 AFD_DbgPrint(MID_TRACE
,("Going to bound state\n"));
347 FCB
->State
= SOCKET_STATE_BOUND
;
348 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
351 /* Succeed pending irps on the FUNCTION_CONNECT list */
352 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_CONNECT
] ) ) {
353 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_CONNECT
]);
354 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
355 AFD_DbgPrint(MID_TRACE
,("Completing connect %p\n", NextIrp
));
356 NextIrp
->IoStatus
.Status
= Status
;
357 NextIrp
->IoStatus
.Information
= NT_SUCCESS(Status
) ? ((ULONG_PTR
)FCB
->Connection
.Handle
) : 0;
358 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
359 (void)IoSetCancelRoutine(NextIrp
, NULL
);
360 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
363 if( NT_SUCCESS(Status
) ) {
364 Status
= MakeSocketIntoConnection( FCB
);
366 if( !NT_SUCCESS(Status
) ) {
367 SocketStateUnlock( FCB
);
371 FCB
->FilledConnectData
= MIN(FCB
->ConnectReturnInfo
->UserDataLength
, FCB
->ConnectDataSize
);
372 if (FCB
->FilledConnectData
)
374 RtlCopyMemory(FCB
->ConnectData
,
375 FCB
->ConnectReturnInfo
->UserData
,
376 FCB
->FilledConnectData
);
379 FCB
->FilledConnectOptions
= MIN(FCB
->ConnectReturnInfo
->OptionsLength
, FCB
->ConnectOptionsSize
);
380 if (FCB
->FilledConnectOptions
)
382 RtlCopyMemory(FCB
->ConnectOptions
,
383 FCB
->ConnectReturnInfo
->Options
,
384 FCB
->FilledConnectOptions
);
387 if( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_SEND
] ) ) {
388 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
]);
389 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
,
390 Tail
.Overlay
.ListEntry
);
391 AFD_DbgPrint(MID_TRACE
,("Launching send request %p\n", NextIrp
));
392 Status
= AfdConnectedSocketWriteData
395 IoGetCurrentIrpStackLocation( NextIrp
),
399 if( Status
== STATUS_PENDING
)
400 Status
= STATUS_SUCCESS
;
403 SocketStateUnlock( FCB
);
405 AFD_DbgPrint(MID_TRACE
,("Returning %x\n", Status
));
410 /* Return the socket object for ths request only if it is a connected or
414 AfdStreamSocketConnect(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
415 PIO_STACK_LOCATION IrpSp
) {
416 NTSTATUS Status
= STATUS_INVALID_PARAMETER
;
417 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
418 PAFD_FCB FCB
= FileObject
->FsContext
;
419 PAFD_CONNECT_INFO ConnectReq
;
420 AFD_DbgPrint(MID_TRACE
,("Called on %p\n", FCB
));
422 UNREFERENCED_PARAMETER(DeviceObject
);
424 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
425 if( !(ConnectReq
= LockRequest( Irp
, IrpSp
, FALSE
, NULL
)) )
426 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
, Irp
,
429 AFD_DbgPrint(MID_TRACE
,("Connect request:\n"));
433 IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
);
436 if( FCB
->Flags
& AFD_ENDPOINT_CONNECTIONLESS
)
438 if( FCB
->RemoteAddress
) ExFreePool( FCB
->RemoteAddress
);
440 TaCopyTransportAddress( &ConnectReq
->RemoteAddress
);
442 if( !FCB
->RemoteAddress
)
443 Status
= STATUS_NO_MEMORY
;
445 Status
= STATUS_SUCCESS
;
447 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
450 switch( FCB
->State
) {
451 case SOCKET_STATE_CONNECTED
:
452 Status
= STATUS_SUCCESS
;
455 case SOCKET_STATE_CONNECTING
:
456 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_CONNECT
);
458 case SOCKET_STATE_CREATED
:
459 if( FCB
->LocalAddress
) ExFreePool( FCB
->LocalAddress
);
461 TaBuildNullTransportAddress( ConnectReq
->RemoteAddress
.Address
[0].AddressType
);
463 if( FCB
->LocalAddress
) {
464 Status
= WarmSocketForBind( FCB
, AFD_SHARE_WILDCARD
);
466 if( NT_SUCCESS(Status
) )
467 FCB
->State
= SOCKET_STATE_BOUND
;
469 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
471 return UnlockAndMaybeComplete
472 ( FCB
, STATUS_NO_MEMORY
, Irp
, 0 );
474 /* Drop through to SOCKET_STATE_BOUND */
476 case SOCKET_STATE_BOUND
:
477 if( FCB
->RemoteAddress
) ExFreePool( FCB
->RemoteAddress
);
479 TaCopyTransportAddress( &ConnectReq
->RemoteAddress
);
481 if( !FCB
->RemoteAddress
) {
482 Status
= STATUS_NO_MEMORY
;
486 Status
= WarmSocketForConnection( FCB
);
488 if( !NT_SUCCESS(Status
) )
491 if (FCB
->ConnectReturnInfo
) ExFreePool(FCB
->ConnectReturnInfo
);
492 Status
= TdiBuildConnectionInfo
493 ( &FCB
->ConnectReturnInfo
,
494 &ConnectReq
->RemoteAddress
);
496 if( NT_SUCCESS(Status
) )
498 if (FCB
->ConnectCallInfo
) ExFreePool(FCB
->ConnectCallInfo
);
499 Status
= TdiBuildConnectionInfo(&FCB
->ConnectCallInfo
,
500 &ConnectReq
->RemoteAddress
);
505 if( NT_SUCCESS(Status
) ) {
506 FCB
->ConnectCallInfo
->UserData
= FCB
->ConnectData
;
507 FCB
->ConnectCallInfo
->UserDataLength
= FCB
->ConnectDataSize
;
508 FCB
->ConnectCallInfo
->Options
= FCB
->ConnectOptions
;
509 FCB
->ConnectCallInfo
->OptionsLength
= FCB
->ConnectOptionsSize
;
511 FCB
->State
= SOCKET_STATE_CONNECTING
;
513 AFD_DbgPrint(MID_TRACE
,("Queueing IRP %p\n", Irp
));
514 Status
= QueueUserModeIrp( FCB
, Irp
, FUNCTION_CONNECT
);
515 if (Status
== STATUS_PENDING
)
517 Status
= TdiConnect( &FCB
->ConnectIrp
.InFlightRequest
,
518 FCB
->Connection
.Object
,
519 FCB
->ConnectCallInfo
,
520 FCB
->ConnectReturnInfo
,
521 &FCB
->ConnectIrp
.Iosb
,
522 StreamSocketConnectComplete
,
526 if (Status
!= STATUS_PENDING
)
527 FCB
->State
= SOCKET_STATE_BOUND
;
529 SocketStateUnlock(FCB
);
536 AFD_DbgPrint(MIN_TRACE
,("Inappropriate socket state %u for connect\n",
541 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );