Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenconnect.c
Go to the documentation of this file.
00001 /* $Id: connect.c 56389 2012-04-22 13:11:54Z tfaber $ 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS kernel 00004 * FILE: drivers/net/afd/afd/connect.c 00005 * PURPOSE: Ancillary functions driver 00006 * PROGRAMMER: Art Yerkes (ayerkes@speakeasy.net) 00007 * UPDATE HISTORY: 00008 * 20040708 Created 00009 */ 00010 #include "afd.h" 00011 00012 NTSTATUS 00013 NTAPI 00014 AfdGetConnectOptions(PDEVICE_OBJECT DeviceObject, PIRP Irp, 00015 PIO_STACK_LOCATION IrpSp) 00016 { 00017 PFILE_OBJECT FileObject = IrpSp->FileObject; 00018 PAFD_FCB FCB = FileObject->FsContext; 00019 UINT BufferSize = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; 00020 00021 if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp); 00022 00023 if (FCB->ConnectOptionsSize == 0) 00024 { 00025 AFD_DbgPrint(MIN_TRACE,("Invalid parameter\n")); 00026 return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0); 00027 } 00028 00029 ASSERT(FCB->ConnectOptions); 00030 00031 if (FCB->FilledConnectOptions < BufferSize) BufferSize = FCB->FilledConnectOptions; 00032 00033 RtlCopyMemory(Irp->UserBuffer, 00034 FCB->ConnectOptions, 00035 BufferSize); 00036 00037 return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, BufferSize); 00038 } 00039 00040 NTSTATUS 00041 NTAPI 00042 AfdSetConnectOptions(PDEVICE_OBJECT DeviceObject, PIRP Irp, 00043 PIO_STACK_LOCATION IrpSp) 00044 { 00045 PFILE_OBJECT FileObject = IrpSp->FileObject; 00046 PAFD_FCB FCB = FileObject->FsContext; 00047 PVOID ConnectOptions = LockRequest(Irp, IrpSp); 00048 UINT ConnectOptionsSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; 00049 00050 if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp); 00051 00052 if (!ConnectOptions) 00053 return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0); 00054 00055 if (FCB->ConnectOptions) 00056 { 00057 ExFreePool(FCB->ConnectOptions); 00058 FCB->ConnectOptions = NULL; 00059 FCB->ConnectOptionsSize = 0; 00060 FCB->FilledConnectOptions = 0; 00061 } 00062 00063 FCB->ConnectOptions = ExAllocatePool(PagedPool, ConnectOptionsSize); 00064 if (!FCB->ConnectOptions) 00065 return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0); 00066 00067 RtlCopyMemory(FCB->ConnectOptions, 00068 ConnectOptions, 00069 ConnectOptionsSize); 00070 00071 FCB->ConnectOptionsSize = ConnectOptionsSize; 00072 00073 return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, 0); 00074 } 00075 00076 NTSTATUS 00077 NTAPI 00078 AfdSetConnectOptionsSize(PDEVICE_OBJECT DeviceObject, PIRP Irp, 00079 PIO_STACK_LOCATION IrpSp) 00080 { 00081 PFILE_OBJECT FileObject = IrpSp->FileObject; 00082 PAFD_FCB FCB = FileObject->FsContext; 00083 PUINT ConnectOptionsSize = LockRequest(Irp, IrpSp); 00084 UINT BufferSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; 00085 00086 if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp); 00087 00088 if (!ConnectOptionsSize) 00089 return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0); 00090 00091 if (BufferSize < sizeof(UINT)) 00092 { 00093 AFD_DbgPrint(MIN_TRACE,("Buffer too small\n")); 00094 return UnlockAndMaybeComplete(FCB, STATUS_BUFFER_TOO_SMALL, Irp, 0); 00095 } 00096 00097 if (FCB->ConnectOptions) 00098 { 00099 ExFreePool(FCB->ConnectOptions); 00100 FCB->ConnectOptionsSize = 0; 00101 FCB->FilledConnectOptions = 0; 00102 } 00103 00104 FCB->ConnectOptions = ExAllocatePool(PagedPool, *ConnectOptionsSize); 00105 if (!FCB->ConnectOptions) return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0); 00106 00107 FCB->ConnectOptionsSize = *ConnectOptionsSize; 00108 00109 return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, 0); 00110 } 00111 00112 NTSTATUS 00113 NTAPI 00114 AfdGetConnectData(PDEVICE_OBJECT DeviceObject, PIRP Irp, 00115 PIO_STACK_LOCATION IrpSp) 00116 { 00117 PFILE_OBJECT FileObject = IrpSp->FileObject; 00118 PAFD_FCB FCB = FileObject->FsContext; 00119 UINT BufferSize = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; 00120 00121 if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp); 00122 00123 if (FCB->ConnectDataSize == 0) 00124 { 00125 AFD_DbgPrint(MIN_TRACE,("Invalid parameter\n")); 00126 return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0); 00127 } 00128 00129 ASSERT(FCB->ConnectData); 00130 00131 if (FCB->FilledConnectData < BufferSize) BufferSize = FCB->FilledConnectData; 00132 00133 RtlCopyMemory(Irp->UserBuffer, 00134 FCB->ConnectData, 00135 BufferSize); 00136 00137 return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, BufferSize); 00138 } 00139 00140 NTSTATUS 00141 NTAPI 00142 AfdSetConnectData(PDEVICE_OBJECT DeviceObject, PIRP Irp, 00143 PIO_STACK_LOCATION IrpSp) 00144 { 00145 PFILE_OBJECT FileObject = IrpSp->FileObject; 00146 PAFD_FCB FCB = FileObject->FsContext; 00147 PVOID ConnectData = LockRequest(Irp, IrpSp); 00148 UINT ConnectDataSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; 00149 00150 if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp); 00151 00152 if (!ConnectData) 00153 return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0); 00154 00155 if (FCB->ConnectData) 00156 { 00157 ExFreePool(FCB->ConnectData); 00158 FCB->ConnectData = NULL; 00159 FCB->ConnectDataSize = 0; 00160 FCB->FilledConnectData = 0; 00161 } 00162 00163 FCB->ConnectData = ExAllocatePool(PagedPool, ConnectDataSize); 00164 if (!FCB->ConnectData) return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0); 00165 00166 RtlCopyMemory(FCB->ConnectData, 00167 ConnectData, 00168 ConnectDataSize); 00169 00170 FCB->ConnectDataSize = ConnectDataSize; 00171 00172 return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, 0); 00173 } 00174 00175 NTSTATUS 00176 NTAPI 00177 AfdSetConnectDataSize(PDEVICE_OBJECT DeviceObject, PIRP Irp, 00178 PIO_STACK_LOCATION IrpSp) 00179 { 00180 PFILE_OBJECT FileObject = IrpSp->FileObject; 00181 PAFD_FCB FCB = FileObject->FsContext; 00182 PUINT ConnectDataSize = LockRequest(Irp, IrpSp); 00183 UINT BufferSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; 00184 00185 if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp); 00186 00187 if (!ConnectDataSize) 00188 return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0); 00189 00190 if (BufferSize < sizeof(UINT)) 00191 { 00192 AFD_DbgPrint(MIN_TRACE,("Buffer too small\n")); 00193 return UnlockAndMaybeComplete(FCB, STATUS_BUFFER_TOO_SMALL, Irp, 0); 00194 } 00195 00196 if (FCB->ConnectData) 00197 { 00198 ExFreePool(FCB->ConnectData); 00199 FCB->ConnectDataSize = 0; 00200 FCB->FilledConnectData = 0; 00201 } 00202 00203 FCB->ConnectData = ExAllocatePool(PagedPool, *ConnectDataSize); 00204 if (!FCB->ConnectData) return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0); 00205 00206 FCB->ConnectDataSize = *ConnectDataSize; 00207 00208 return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, 0); 00209 } 00210 00211 00212 NTSTATUS 00213 WarmSocketForConnection(PAFD_FCB FCB) { 00214 NTSTATUS Status; 00215 00216 if( !FCB->TdiDeviceName.Length || !FCB->TdiDeviceName.Buffer ) { 00217 AFD_DbgPrint(MIN_TRACE,("Null Device\n")); 00218 return STATUS_NO_SUCH_DEVICE; 00219 } 00220 00221 Status = TdiOpenConnectionEndpointFile(&FCB->TdiDeviceName, 00222 &FCB->Connection.Handle, 00223 &FCB->Connection.Object ); 00224 00225 if( NT_SUCCESS(Status) ) { 00226 Status = TdiAssociateAddressFile( FCB->AddressFile.Handle, 00227 FCB->Connection.Object ); 00228 } 00229 00230 return Status; 00231 } 00232 00233 NTSTATUS 00234 MakeSocketIntoConnection(PAFD_FCB FCB) { 00235 NTSTATUS Status; 00236 00237 ASSERT(!FCB->Recv.Window); 00238 ASSERT(!FCB->Send.Window); 00239 00240 if (!FCB->Recv.Size) 00241 { 00242 Status = TdiQueryMaxDatagramLength(FCB->Connection.Object, 00243 &FCB->Recv.Size); 00244 if (!NT_SUCCESS(Status)) 00245 return Status; 00246 } 00247 00248 if (!FCB->Send.Size) 00249 { 00250 Status = TdiQueryMaxDatagramLength(FCB->Connection.Object, 00251 &FCB->Send.Size); 00252 if (!NT_SUCCESS(Status)) 00253 return Status; 00254 } 00255 00256 /* Allocate the receive area and start receiving */ 00257 if (!FCB->Recv.Window) 00258 { 00259 FCB->Recv.Window = ExAllocatePool( PagedPool, FCB->Recv.Size ); 00260 if( !FCB->Recv.Window ) return STATUS_NO_MEMORY; 00261 } 00262 00263 if (!FCB->Send.Window) 00264 { 00265 FCB->Send.Window = ExAllocatePool( PagedPool, FCB->Send.Size ); 00266 if( !FCB->Send.Window ) return STATUS_NO_MEMORY; 00267 } 00268 00269 FCB->State = SOCKET_STATE_CONNECTED; 00270 00271 Status = TdiReceive( &FCB->ReceiveIrp.InFlightRequest, 00272 FCB->Connection.Object, 00273 TDI_RECEIVE_NORMAL, 00274 FCB->Recv.Window, 00275 FCB->Recv.Size, 00276 &FCB->ReceiveIrp.Iosb, 00277 ReceiveComplete, 00278 FCB ); 00279 00280 if( Status == STATUS_PENDING ) Status = STATUS_SUCCESS; 00281 00282 FCB->PollState |= AFD_EVENT_CONNECT | AFD_EVENT_SEND; 00283 FCB->PollStatus[FD_CONNECT_BIT] = STATUS_SUCCESS; 00284 FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS; 00285 PollReeval( FCB->DeviceExt, FCB->FileObject ); 00286 00287 return Status; 00288 } 00289 00290 static 00291 NTSTATUS 00292 NTAPI 00293 StreamSocketConnectComplete(PDEVICE_OBJECT DeviceObject, PIRP Irp, 00294 PVOID Context) { 00295 NTSTATUS Status = Irp->IoStatus.Status; 00296 PAFD_FCB FCB = (PAFD_FCB)Context; 00297 PLIST_ENTRY NextIrpEntry; 00298 PIRP NextIrp; 00299 00300 AFD_DbgPrint(MID_TRACE,("Called: FCB %x, FO %x\n", 00301 Context, FCB->FileObject)); 00302 00303 /* I was wrong about this before as we can have pending writes to a not 00304 * yet connected socket */ 00305 if( !SocketAcquireStateLock( FCB ) ) 00306 return STATUS_FILE_CLOSED; 00307 00308 AFD_DbgPrint(MID_TRACE,("Irp->IoStatus.Status = %x\n", 00309 Irp->IoStatus.Status)); 00310 00311 ASSERT(FCB->ConnectIrp.InFlightRequest == Irp); 00312 FCB->ConnectIrp.InFlightRequest = NULL; 00313 00314 if( FCB->State == SOCKET_STATE_CLOSED ) { 00315 /* Cleanup our IRP queue because the FCB is being destroyed */ 00316 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_CONNECT] ) ) { 00317 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_CONNECT]); 00318 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry); 00319 NextIrp->IoStatus.Status = STATUS_FILE_CLOSED; 00320 NextIrp->IoStatus.Information = 0; 00321 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); 00322 (void)IoSetCancelRoutine(NextIrp, NULL); 00323 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); 00324 } 00325 SocketStateUnlock( FCB ); 00326 return STATUS_FILE_CLOSED; 00327 } 00328 00329 if( !NT_SUCCESS(Irp->IoStatus.Status) ) { 00330 FCB->PollState |= AFD_EVENT_CONNECT_FAIL; 00331 FCB->PollStatus[FD_CONNECT_BIT] = Irp->IoStatus.Status; 00332 AFD_DbgPrint(MID_TRACE,("Going to bound state\n")); 00333 FCB->State = SOCKET_STATE_BOUND; 00334 PollReeval( FCB->DeviceExt, FCB->FileObject ); 00335 } 00336 00337 /* Succeed pending irps on the FUNCTION_CONNECT list */ 00338 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_CONNECT] ) ) { 00339 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_CONNECT]); 00340 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry); 00341 AFD_DbgPrint(MID_TRACE,("Completing connect %x\n", NextIrp)); 00342 NextIrp->IoStatus.Status = Status; 00343 NextIrp->IoStatus.Information = NT_SUCCESS(Status) ? ((ULONG_PTR)FCB->Connection.Handle) : 0; 00344 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); 00345 (void)IoSetCancelRoutine(NextIrp, NULL); 00346 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); 00347 } 00348 00349 if( NT_SUCCESS(Status) ) { 00350 Status = MakeSocketIntoConnection( FCB ); 00351 00352 if( !NT_SUCCESS(Status) ) { 00353 SocketStateUnlock( FCB ); 00354 return Status; 00355 } 00356 00357 FCB->FilledConnectData = MIN(FCB->ConnectReturnInfo->UserDataLength, FCB->ConnectDataSize); 00358 if (FCB->FilledConnectData) 00359 { 00360 RtlCopyMemory(FCB->ConnectData, 00361 FCB->ConnectReturnInfo->UserData, 00362 FCB->FilledConnectData); 00363 } 00364 00365 FCB->FilledConnectOptions = MIN(FCB->ConnectReturnInfo->OptionsLength, FCB->ConnectOptionsSize); 00366 if (FCB->FilledConnectOptions) 00367 { 00368 RtlCopyMemory(FCB->ConnectOptions, 00369 FCB->ConnectReturnInfo->Options, 00370 FCB->FilledConnectOptions); 00371 } 00372 00373 if( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) { 00374 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]); 00375 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, 00376 Tail.Overlay.ListEntry); 00377 AFD_DbgPrint(MID_TRACE,("Launching send request %x\n", NextIrp)); 00378 Status = AfdConnectedSocketWriteData 00379 ( DeviceObject, 00380 NextIrp, 00381 IoGetCurrentIrpStackLocation( NextIrp ), 00382 FALSE ); 00383 } 00384 00385 if( Status == STATUS_PENDING ) 00386 Status = STATUS_SUCCESS; 00387 } 00388 00389 SocketStateUnlock( FCB ); 00390 00391 AFD_DbgPrint(MID_TRACE,("Returning %x\n", Status)); 00392 00393 return Status; 00394 } 00395 00396 /* Return the socket object for ths request only if it is a connected or 00397 stream type. */ 00398 NTSTATUS 00399 NTAPI 00400 AfdStreamSocketConnect(PDEVICE_OBJECT DeviceObject, PIRP Irp, 00401 PIO_STACK_LOCATION IrpSp) { 00402 NTSTATUS Status = STATUS_INVALID_PARAMETER; 00403 PFILE_OBJECT FileObject = IrpSp->FileObject; 00404 PAFD_FCB FCB = FileObject->FsContext; 00405 PAFD_CONNECT_INFO ConnectReq; 00406 AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB)); 00407 00408 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp ); 00409 if( !(ConnectReq = LockRequest( Irp, IrpSp )) ) 00410 return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, Irp, 00411 0 ); 00412 00413 AFD_DbgPrint(MID_TRACE,("Connect request:\n")); 00414 #if 0 00415 OskitDumpBuffer 00416 ( (PCHAR)ConnectReq, 00417 IrpSp->Parameters.DeviceIoControl.InputBufferLength ); 00418 #endif 00419 00420 if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS ) 00421 { 00422 if( FCB->RemoteAddress ) ExFreePool( FCB->RemoteAddress ); 00423 FCB->RemoteAddress = 00424 TaCopyTransportAddress( &ConnectReq->RemoteAddress ); 00425 00426 if( !FCB->RemoteAddress ) 00427 Status = STATUS_NO_MEMORY; 00428 else 00429 Status = STATUS_SUCCESS; 00430 00431 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); 00432 } 00433 00434 switch( FCB->State ) { 00435 case SOCKET_STATE_CONNECTED: 00436 Status = STATUS_SUCCESS; 00437 break; 00438 00439 case SOCKET_STATE_CONNECTING: 00440 return LeaveIrpUntilLater( FCB, Irp, FUNCTION_CONNECT ); 00441 00442 case SOCKET_STATE_CREATED: 00443 if( FCB->LocalAddress ) ExFreePool( FCB->LocalAddress ); 00444 FCB->LocalAddress = 00445 TaBuildNullTransportAddress( ConnectReq->RemoteAddress.Address[0].AddressType ); 00446 00447 if( FCB->LocalAddress ) { 00448 Status = WarmSocketForBind( FCB ); 00449 00450 if( NT_SUCCESS(Status) ) 00451 FCB->State = SOCKET_STATE_BOUND; 00452 else 00453 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); 00454 } else 00455 return UnlockAndMaybeComplete 00456 ( FCB, STATUS_NO_MEMORY, Irp, 0 ); 00457 00458 /* Drop through to SOCKET_STATE_BOUND */ 00459 00460 case SOCKET_STATE_BOUND: 00461 if( FCB->RemoteAddress ) ExFreePool( FCB->RemoteAddress ); 00462 FCB->RemoteAddress = 00463 TaCopyTransportAddress( &ConnectReq->RemoteAddress ); 00464 00465 if( !FCB->RemoteAddress ) { 00466 Status = STATUS_NO_MEMORY; 00467 break; 00468 } 00469 00470 Status = WarmSocketForConnection( FCB ); 00471 00472 if( !NT_SUCCESS(Status) ) 00473 break; 00474 00475 if (FCB->ConnectReturnInfo) ExFreePool(FCB->ConnectReturnInfo); 00476 Status = TdiBuildConnectionInfo 00477 ( &FCB->ConnectReturnInfo, 00478 &ConnectReq->RemoteAddress ); 00479 00480 if( NT_SUCCESS(Status) ) 00481 { 00482 if (FCB->ConnectCallInfo) ExFreePool(FCB->ConnectCallInfo); 00483 Status = TdiBuildConnectionInfo(&FCB->ConnectCallInfo, 00484 &ConnectReq->RemoteAddress); 00485 } 00486 else break; 00487 00488 00489 if( NT_SUCCESS(Status) ) { 00490 FCB->ConnectCallInfo->UserData = FCB->ConnectData; 00491 FCB->ConnectCallInfo->UserDataLength = FCB->ConnectDataSize; 00492 FCB->ConnectCallInfo->Options = FCB->ConnectOptions; 00493 FCB->ConnectCallInfo->OptionsLength = FCB->ConnectOptionsSize; 00494 00495 FCB->State = SOCKET_STATE_CONNECTING; 00496 00497 AFD_DbgPrint(MID_TRACE,("Queueing IRP %x\n", Irp)); 00498 Status = QueueUserModeIrp( FCB, Irp, FUNCTION_CONNECT ); 00499 if (Status == STATUS_PENDING) 00500 { 00501 Status = TdiConnect( &FCB->ConnectIrp.InFlightRequest, 00502 FCB->Connection.Object, 00503 FCB->ConnectCallInfo, 00504 FCB->ConnectReturnInfo, 00505 &FCB->ConnectIrp.Iosb, 00506 StreamSocketConnectComplete, 00507 FCB ); 00508 } 00509 00510 if (Status != STATUS_PENDING) 00511 FCB->State = SOCKET_STATE_BOUND; 00512 00513 SocketStateUnlock(FCB); 00514 00515 return Status; 00516 } 00517 break; 00518 00519 default: 00520 AFD_DbgPrint(MIN_TRACE,("Inappropriate socket state %d for connect\n", 00521 FCB->State)); 00522 break; 00523 } 00524 00525 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); 00526 } Generated on Sat May 26 2012 04:21:03 for ReactOS by
1.7.6.1
|