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 FCB
->PollStatus
[FD_CONNECT_BIT
] = STATUS_SUCCESS
;
251 FCB
->PollStatus
[FD_WRITE_BIT
] = STATUS_SUCCESS
;
252 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
257 static NTSTATUS NTAPI StreamSocketConnectComplete
258 ( PDEVICE_OBJECT DeviceObject
,
261 NTSTATUS Status
= Irp
->IoStatus
.Status
;
262 PAFD_FCB FCB
= (PAFD_FCB
)Context
;
263 PLIST_ENTRY NextIrpEntry
;
266 AFD_DbgPrint(MID_TRACE
,("Called: FCB %x, FO %x\n",
267 Context
, FCB
->FileObject
));
269 /* I was wrong about this before as we can have pending writes to a not
270 * yet connected socket */
271 if( !SocketAcquireStateLock( FCB
) )
272 return STATUS_FILE_CLOSED
;
274 AFD_DbgPrint(MID_TRACE
,("Irp->IoStatus.Status = %x\n",
275 Irp
->IoStatus
.Status
));
277 FCB
->ConnectIrp
.InFlightRequest
= NULL
;
279 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
280 /* Cleanup our IRP queue because the FCB is being destroyed */
281 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_CONNECT
] ) ) {
282 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_CONNECT
]);
283 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
284 NextIrp
->IoStatus
.Status
= STATUS_FILE_CLOSED
;
285 NextIrp
->IoStatus
.Information
= 0;
286 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
287 (void)IoSetCancelRoutine(NextIrp
, NULL
);
288 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
290 SocketStateUnlock( FCB
);
291 return STATUS_FILE_CLOSED
;
294 if( !NT_SUCCESS(Irp
->IoStatus
.Status
) ) {
295 FCB
->PollState
|= AFD_EVENT_CONNECT_FAIL
;
296 FCB
->PollStatus
[FD_CONNECT_BIT
] = Irp
->IoStatus
.Status
;
297 AFD_DbgPrint(MID_TRACE
,("Going to bound state\n"));
298 FCB
->State
= SOCKET_STATE_BOUND
;
299 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
302 /* Succeed pending irps on the FUNCTION_CONNECT list */
303 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_CONNECT
] ) ) {
304 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_CONNECT
]);
305 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
306 AFD_DbgPrint(MID_TRACE
,("Completing connect %x\n", NextIrp
));
307 NextIrp
->IoStatus
.Status
= Status
;
308 NextIrp
->IoStatus
.Information
= NT_SUCCESS(Status
) ? ((ULONG_PTR
)FCB
->Connection
.Handle
) : 0;
309 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
310 (void)IoSetCancelRoutine(NextIrp
, NULL
);
311 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
314 if( NT_SUCCESS(Status
) ) {
315 Status
= MakeSocketIntoConnection( FCB
);
317 if( !NT_SUCCESS(Status
) ) {
318 SocketStateUnlock( FCB
);
322 FCB
->FilledConnectData
= MIN(FCB
->ConnectInfo
->UserDataLength
, FCB
->ConnectDataSize
);
323 if (FCB
->FilledConnectData
)
325 RtlCopyMemory(FCB
->ConnectData
,
326 FCB
->ConnectInfo
->UserData
,
327 FCB
->FilledConnectData
);
330 FCB
->FilledConnectOptions
= MIN(FCB
->ConnectInfo
->OptionsLength
, FCB
->ConnectOptionsSize
);
331 if (FCB
->FilledConnectOptions
)
333 RtlCopyMemory(FCB
->ConnectOptions
,
334 FCB
->ConnectInfo
->Options
,
335 FCB
->FilledConnectOptions
);
338 if( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_SEND
] ) ) {
339 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
]);
340 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
,
341 Tail
.Overlay
.ListEntry
);
342 AFD_DbgPrint(MID_TRACE
,("Launching send request %x\n", NextIrp
));
343 Status
= AfdConnectedSocketWriteData
346 IoGetCurrentIrpStackLocation( NextIrp
),
350 if( Status
== STATUS_PENDING
)
351 Status
= STATUS_SUCCESS
;
354 SocketStateUnlock( FCB
);
356 AFD_DbgPrint(MID_TRACE
,("Returning %x\n", Status
));
361 /* Return the socket object for ths request only if it is a connected or
364 AfdStreamSocketConnect(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
365 PIO_STACK_LOCATION IrpSp
) {
366 NTSTATUS Status
= STATUS_INVALID_PARAMETER
;
367 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
368 PAFD_FCB FCB
= FileObject
->FsContext
;
369 PAFD_CONNECT_INFO ConnectReq
;
370 PTDI_CONNECTION_INFORMATION TargetAddress
;
371 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
373 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
374 if( !(ConnectReq
= LockRequest( Irp
, IrpSp
)) )
375 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
, Irp
,
378 AFD_DbgPrint(MID_TRACE
,("Connect request:\n"));
382 IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
);
385 if( FCB
->Flags
& AFD_ENDPOINT_CONNECTIONLESS
)
387 if( FCB
->RemoteAddress
) ExFreePool( FCB
->RemoteAddress
);
389 TaCopyTransportAddress( &ConnectReq
->RemoteAddress
);
391 if( !FCB
->RemoteAddress
)
392 Status
= STATUS_NO_MEMORY
;
394 Status
= STATUS_SUCCESS
;
396 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
399 switch( FCB
->State
) {
400 case SOCKET_STATE_CONNECTED
:
401 Status
= STATUS_SUCCESS
;
404 case SOCKET_STATE_CONNECTING
:
405 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_CONNECT
);
407 case SOCKET_STATE_CREATED
:
408 if( FCB
->LocalAddress
) ExFreePool( FCB
->LocalAddress
);
410 TaCopyTransportAddress( &ConnectReq
->RemoteAddress
);
412 if( FCB
->LocalAddress
) {
413 Status
= WarmSocketForBind( FCB
);
415 if( NT_SUCCESS(Status
) )
416 FCB
->State
= SOCKET_STATE_BOUND
;
418 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
420 return UnlockAndMaybeComplete
421 ( FCB
, STATUS_NO_MEMORY
, Irp
, 0 );
423 /* Drop through to SOCKET_STATE_BOUND */
425 case SOCKET_STATE_BOUND
:
426 if( FCB
->RemoteAddress
) ExFreePool( FCB
->RemoteAddress
);
428 TaCopyTransportAddress( &ConnectReq
->RemoteAddress
);
430 if( !FCB
->RemoteAddress
) {
431 Status
= STATUS_NO_MEMORY
;
435 Status
= WarmSocketForConnection( FCB
);
437 if( !NT_SUCCESS(Status
) )
440 Status
= TdiBuildConnectionInfo
442 &ConnectReq
->RemoteAddress
);
444 if( NT_SUCCESS(Status
) )
445 Status
= TdiBuildConnectionInfo(&TargetAddress
,
446 &ConnectReq
->RemoteAddress
);
450 if( NT_SUCCESS(Status
) ) {
451 TargetAddress
->UserData
= FCB
->ConnectData
;
452 TargetAddress
->UserDataLength
= FCB
->ConnectDataSize
;
453 TargetAddress
->Options
= FCB
->ConnectOptions
;
454 TargetAddress
->OptionsLength
= FCB
->ConnectOptionsSize
;
456 Status
= TdiConnect( &FCB
->ConnectIrp
.InFlightRequest
,
457 FCB
->Connection
.Object
,
460 &FCB
->ConnectIrp
.Iosb
,
461 StreamSocketConnectComplete
,
464 ExFreePool(TargetAddress
);
466 AFD_DbgPrint(MID_TRACE
,("Queueing IRP %x\n", Irp
));
468 if( Status
== STATUS_PENDING
) {
469 FCB
->State
= SOCKET_STATE_CONNECTING
;
470 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_CONNECT
);
476 AFD_DbgPrint(MID_TRACE
,("Inappropriate socket state %d for connect\n",
481 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );