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)
11 #include "tdi_proto.h"
16 AfdGetConnectOptions(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
17 PIO_STACK_LOCATION IrpSp
)
19 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
20 PAFD_FCB FCB
= FileObject
->FsContext
;
21 UINT BufferSize
= IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
;
23 if (!SocketAcquireStateLock(FCB
)) return LostSocket(Irp
);
25 if (FCB
->ConnectOptionsSize
== 0)
26 return UnlockAndMaybeComplete(FCB
, STATUS_INVALID_PARAMETER
, Irp
, 0);
28 ASSERT(FCB
->ConnectOptions
);
30 if (FCB
->FilledConnectOptions
< BufferSize
) BufferSize
= FCB
->FilledConnectOptions
;
32 RtlCopyMemory(Irp
->UserBuffer
,
36 return UnlockAndMaybeComplete(FCB
, STATUS_SUCCESS
, Irp
, BufferSize
);
41 AfdSetConnectOptions(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
42 PIO_STACK_LOCATION IrpSp
)
44 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
45 PAFD_FCB FCB
= FileObject
->FsContext
;
46 PVOID ConnectOptions
= IrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
47 UINT ConnectOptionsSize
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
49 if (!SocketAcquireStateLock(FCB
)) return LostSocket(Irp
);
51 if (FCB
->ConnectOptions
)
53 ExFreePool(FCB
->ConnectOptions
);
54 FCB
->ConnectOptions
= NULL
;
55 FCB
->ConnectOptionsSize
= 0;
56 FCB
->FilledConnectOptions
= 0;
59 FCB
->ConnectOptions
= ExAllocatePool(PagedPool
, ConnectOptionsSize
);
60 if (!FCB
->ConnectOptions
) return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
62 RtlCopyMemory(FCB
->ConnectOptions
,
66 FCB
->ConnectOptionsSize
= ConnectOptionsSize
;
68 return UnlockAndMaybeComplete(FCB
, STATUS_SUCCESS
, Irp
, 0);
73 AfdSetConnectOptionsSize(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
74 PIO_STACK_LOCATION IrpSp
)
76 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
77 PAFD_FCB FCB
= FileObject
->FsContext
;
78 PUINT ConnectOptionsSize
= IrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
79 UINT BufferSize
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
81 if (!SocketAcquireStateLock(FCB
)) return LostSocket(Irp
);
83 if (BufferSize
< sizeof(UINT
))
84 return UnlockAndMaybeComplete(FCB
, STATUS_BUFFER_TOO_SMALL
, Irp
, 0);
86 if (FCB
->ConnectOptions
)
88 ExFreePool(FCB
->ConnectOptions
);
89 FCB
->ConnectOptionsSize
= 0;
90 FCB
->FilledConnectOptions
= 0;
93 FCB
->ConnectOptions
= ExAllocatePool(PagedPool
, *ConnectOptionsSize
);
94 if (!FCB
->ConnectOptions
) return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
96 FCB
->ConnectOptionsSize
= *ConnectOptionsSize
;
98 return UnlockAndMaybeComplete(FCB
, STATUS_SUCCESS
, Irp
, 0);
102 AfdGetConnectData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
103 PIO_STACK_LOCATION IrpSp
)
105 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
106 PAFD_FCB FCB
= FileObject
->FsContext
;
107 UINT BufferSize
= IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
;
109 if (!SocketAcquireStateLock(FCB
)) return LostSocket(Irp
);
111 if (FCB
->ConnectDataSize
== 0)
112 return UnlockAndMaybeComplete(FCB
, STATUS_INVALID_PARAMETER
, Irp
, 0);
114 ASSERT(FCB
->ConnectData
);
116 if (FCB
->FilledConnectData
< BufferSize
) BufferSize
= FCB
->FilledConnectData
;
118 RtlCopyMemory(Irp
->UserBuffer
,
122 return UnlockAndMaybeComplete(FCB
, STATUS_SUCCESS
, Irp
, BufferSize
);
127 AfdSetConnectData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
128 PIO_STACK_LOCATION IrpSp
)
130 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
131 PAFD_FCB FCB
= FileObject
->FsContext
;
132 PVOID ConnectData
= IrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
133 UINT ConnectDataSize
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
135 if (!SocketAcquireStateLock(FCB
)) return LostSocket(Irp
);
137 if (FCB
->ConnectData
)
139 ExFreePool(FCB
->ConnectData
);
140 FCB
->ConnectData
= NULL
;
141 FCB
->ConnectDataSize
= 0;
142 FCB
->FilledConnectData
= 0;
145 FCB
->ConnectData
= ExAllocatePool(PagedPool
, ConnectDataSize
);
146 if (!FCB
->ConnectData
) return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
148 RtlCopyMemory(FCB
->ConnectData
,
152 FCB
->ConnectDataSize
= ConnectDataSize
;
154 return UnlockAndMaybeComplete(FCB
, STATUS_SUCCESS
, Irp
, 0);
159 AfdSetConnectDataSize(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
160 PIO_STACK_LOCATION IrpSp
)
162 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
163 PAFD_FCB FCB
= FileObject
->FsContext
;
164 PUINT ConnectDataSize
= IrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
165 UINT BufferSize
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
167 if (!SocketAcquireStateLock(FCB
)) return LostSocket(Irp
);
169 if (BufferSize
< sizeof(UINT
))
170 return UnlockAndMaybeComplete(FCB
, STATUS_BUFFER_TOO_SMALL
, Irp
, 0);
172 if (FCB
->ConnectData
)
174 ExFreePool(FCB
->ConnectData
);
175 FCB
->ConnectDataSize
= 0;
176 FCB
->FilledConnectData
= 0;
179 FCB
->ConnectData
= ExAllocatePool(PagedPool
, *ConnectDataSize
);
180 if (!FCB
->ConnectData
) return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
182 FCB
->ConnectDataSize
= *ConnectDataSize
;
184 return UnlockAndMaybeComplete(FCB
, STATUS_SUCCESS
, Irp
, 0);
188 NTSTATUS
WarmSocketForConnection( PAFD_FCB FCB
) {
191 if( !FCB
->TdiDeviceName
.Length
|| !FCB
->TdiDeviceName
.Buffer
) {
192 AFD_DbgPrint(MID_TRACE
,("Null Device\n"));
193 return STATUS_NO_SUCH_DEVICE
;
196 Status
= TdiOpenConnectionEndpointFile(&FCB
->TdiDeviceName
,
197 &FCB
->Connection
.Handle
,
198 &FCB
->Connection
.Object
);
200 if( NT_SUCCESS(Status
) ) {
201 Status
= TdiAssociateAddressFile( FCB
->AddressFile
.Handle
,
202 FCB
->Connection
.Object
);
208 NTSTATUS
MakeSocketIntoConnection( PAFD_FCB FCB
) {
211 ASSERT(!FCB
->Recv
.Window
);
212 ASSERT(!FCB
->Send
.Window
);
214 Status
= TdiQueryMaxDatagramLength(FCB
->Connection
.Object
,
216 if (!NT_SUCCESS(Status
))
219 FCB
->Recv
.Size
= FCB
->Send
.Size
;
221 /* Allocate the receive area and start receiving */
223 ExAllocatePool( PagedPool
, FCB
->Recv
.Size
);
225 if( !FCB
->Recv
.Window
) return STATUS_NO_MEMORY
;
228 ExAllocatePool( PagedPool
, FCB
->Send
.Size
);
230 if( !FCB
->Send
.Window
) {
231 ExFreePool( FCB
->Recv
.Window
);
232 FCB
->Recv
.Window
= NULL
;
233 return STATUS_NO_MEMORY
;
236 FCB
->State
= SOCKET_STATE_CONNECTED
;
238 Status
= TdiReceive( &FCB
->ReceiveIrp
.InFlightRequest
,
239 FCB
->Connection
.Object
,
243 &FCB
->ReceiveIrp
.Iosb
,
247 if( Status
== STATUS_PENDING
) Status
= STATUS_SUCCESS
;
249 FCB
->PollState
|= AFD_EVENT_CONNECT
| AFD_EVENT_SEND
;
250 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
255 static NTSTATUS NTAPI StreamSocketConnectComplete
256 ( PDEVICE_OBJECT DeviceObject
,
259 NTSTATUS Status
= Irp
->IoStatus
.Status
;
260 PAFD_FCB FCB
= (PAFD_FCB
)Context
;
261 PLIST_ENTRY NextIrpEntry
;
264 AFD_DbgPrint(MID_TRACE
,("Called: FCB %x, FO %x\n",
265 Context
, FCB
->FileObject
));
267 /* I was wrong about this before as we can have pending writes to a not
268 * yet connected socket */
269 if( !SocketAcquireStateLock( FCB
) )
270 return STATUS_FILE_CLOSED
;
272 AFD_DbgPrint(MID_TRACE
,("Irp->IoStatus.Status = %x\n",
273 Irp
->IoStatus
.Status
));
275 FCB
->ConnectIrp
.InFlightRequest
= NULL
;
277 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
278 /* Cleanup our IRP queue because the FCB is being destroyed */
279 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_CONNECT
] ) ) {
280 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_CONNECT
]);
281 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
282 NextIrp
->IoStatus
.Status
= STATUS_FILE_CLOSED
;
283 NextIrp
->IoStatus
.Information
= 0;
284 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
285 (void)IoSetCancelRoutine(NextIrp
, NULL
);
286 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
288 SocketStateUnlock( FCB
);
289 return STATUS_FILE_CLOSED
;
292 if( !NT_SUCCESS(Irp
->IoStatus
.Status
) ) {
293 FCB
->PollState
|= AFD_EVENT_CONNECT_FAIL
;
294 AFD_DbgPrint(MID_TRACE
,("Going to bound state\n"));
295 FCB
->State
= SOCKET_STATE_BOUND
;
296 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
299 /* Succeed pending irps on the FUNCTION_CONNECT list */
300 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_CONNECT
] ) ) {
301 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_CONNECT
]);
302 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
303 AFD_DbgPrint(MID_TRACE
,("Completing connect %x\n", NextIrp
));
304 NextIrp
->IoStatus
.Status
= Status
;
305 NextIrp
->IoStatus
.Information
= NT_SUCCESS(Status
) ? ((ULONG_PTR
)FCB
->Connection
.Handle
) : 0;
306 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
307 (void)IoSetCancelRoutine(NextIrp
, NULL
);
308 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
311 if( NT_SUCCESS(Status
) ) {
312 Status
= MakeSocketIntoConnection( FCB
);
314 if( !NT_SUCCESS(Status
) ) {
315 SocketStateUnlock( FCB
);
319 FCB
->FilledConnectData
= MIN(FCB
->ConnectInfo
->UserDataLength
, FCB
->ConnectDataSize
);
320 if (FCB
->FilledConnectData
)
322 RtlCopyMemory(FCB
->ConnectData
,
323 FCB
->ConnectInfo
->UserData
,
324 FCB
->FilledConnectData
);
327 FCB
->FilledConnectOptions
= MIN(FCB
->ConnectInfo
->OptionsLength
, FCB
->ConnectOptionsSize
);
328 if (FCB
->FilledConnectOptions
)
330 RtlCopyMemory(FCB
->ConnectOptions
,
331 FCB
->ConnectInfo
->Options
,
332 FCB
->FilledConnectOptions
);
335 if( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_SEND
] ) ) {
336 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
]);
337 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
,
338 Tail
.Overlay
.ListEntry
);
339 AFD_DbgPrint(MID_TRACE
,("Launching send request %x\n", NextIrp
));
340 Status
= AfdConnectedSocketWriteData
343 IoGetCurrentIrpStackLocation( NextIrp
),
347 if( Status
== STATUS_PENDING
)
348 Status
= STATUS_SUCCESS
;
351 SocketStateUnlock( FCB
);
353 AFD_DbgPrint(MID_TRACE
,("Returning %x\n", Status
));
358 /* Return the socket object for ths request only if it is a connected or
361 AfdStreamSocketConnect(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
362 PIO_STACK_LOCATION IrpSp
) {
363 NTSTATUS Status
= STATUS_INVALID_PARAMETER
;
364 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
365 PAFD_FCB FCB
= FileObject
->FsContext
;
366 PAFD_CONNECT_INFO ConnectReq
;
367 PTDI_CONNECTION_INFORMATION TargetAddress
;
368 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
370 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
371 if( !(ConnectReq
= LockRequest( Irp
, IrpSp
)) )
372 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
, Irp
,
375 AFD_DbgPrint(MID_TRACE
,("Connect request:\n"));
379 IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
);
382 if( FCB
->Flags
& AFD_ENDPOINT_CONNECTIONLESS
)
383 return UnlockAndMaybeComplete( FCB
, STATUS_INVALID_PARAMETER
, Irp
, 0 );
385 switch( FCB
->State
) {
386 case SOCKET_STATE_CONNECTED
:
387 Status
= STATUS_SUCCESS
;
390 case SOCKET_STATE_CONNECTING
:
391 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_CONNECT
);
393 case SOCKET_STATE_CREATED
:
394 if( FCB
->LocalAddress
) ExFreePool( FCB
->LocalAddress
);
396 TaCopyTransportAddress( &ConnectReq
->RemoteAddress
);
398 if( FCB
->LocalAddress
) {
399 Status
= WarmSocketForBind( FCB
);
401 if( NT_SUCCESS(Status
) )
402 FCB
->State
= SOCKET_STATE_BOUND
;
404 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
406 return UnlockAndMaybeComplete
407 ( FCB
, STATUS_NO_MEMORY
, Irp
, 0 );
409 /* Drop through to SOCKET_STATE_BOUND */
411 case SOCKET_STATE_BOUND
:
412 if( FCB
->RemoteAddress
) ExFreePool( FCB
->RemoteAddress
);
414 TaCopyTransportAddress( &ConnectReq
->RemoteAddress
);
416 if( !FCB
->RemoteAddress
) {
417 Status
= STATUS_NO_MEMORY
;
421 Status
= WarmSocketForConnection( FCB
);
423 if( !NT_SUCCESS(Status
) )
426 Status
= TdiBuildConnectionInfo
428 &ConnectReq
->RemoteAddress
);
430 if( NT_SUCCESS(Status
) )
431 Status
= TdiBuildConnectionInfo(&TargetAddress
,
432 &ConnectReq
->RemoteAddress
);
436 if( NT_SUCCESS(Status
) ) {
437 TargetAddress
->UserData
= FCB
->ConnectData
;
438 TargetAddress
->UserDataLength
= FCB
->ConnectDataSize
;
439 TargetAddress
->Options
= FCB
->ConnectOptions
;
440 TargetAddress
->OptionsLength
= FCB
->ConnectOptionsSize
;
442 Status
= TdiConnect( &FCB
->ConnectIrp
.InFlightRequest
,
443 FCB
->Connection
.Object
,
446 &FCB
->ConnectIrp
.Iosb
,
447 StreamSocketConnectComplete
,
450 ExFreePool(TargetAddress
);
452 AFD_DbgPrint(MID_TRACE
,("Queueing IRP %x\n", Irp
));
454 if( Status
== STATUS_PENDING
) {
455 FCB
->State
= SOCKET_STATE_CONNECTING
;
456 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_CONNECT
);
462 AFD_DbgPrint(MID_TRACE
,("Inappropriate socket state %d for connect\n",
467 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );