Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenread.c
Go to the documentation of this file.
00001 /* $Id: read.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/read.c 00005 * PURPOSE: Ancillary functions driver 00006 * PROGRAMMER: Art Yerkes (ayerkes@speakeasy.net) 00007 * UPDATE HISTORY: 00008 * 20040708 Created 00009 * 00010 * Improve buffering code 00011 * 00012 * We're keeping data receiving in one of two states: 00013 * A) Some data available in the FCB 00014 * FCB->Recv.BytesUsed != FCB->Recv.Content 00015 * FCB->ReceiveIrp.InFlightRequest == NULL 00016 * AFD_EVENT_RECEIVE set in FCB->PollState 00017 * B) No data available in the FCB 00018 * FCB->Recv.BytesUsed == FCB->Recv.Content (== 0) 00019 * FCB->RecieveIrp.InFlightRequest != NULL 00020 * AFD_EVENT_RECEIVED not set in FCB->PollState 00021 * So basically we either have data available or a TDI receive 00022 * in flight. 00023 */ 00024 #include "afd.h" 00025 00026 static VOID HandleReceiveComplete( PAFD_FCB FCB, NTSTATUS Status, ULONG_PTR Information ) 00027 { 00028 FCB->Recv.BytesUsed = 0; 00029 00030 /* We got closed while the receive was in progress */ 00031 if (FCB->TdiReceiveClosed) 00032 { 00033 FCB->Recv.Content = 0; 00034 } 00035 /* Receive successful with new data */ 00036 else if (Status == STATUS_SUCCESS && Information) 00037 { 00038 FCB->Recv.Content = Information; 00039 } 00040 /* Receive successful with no data (graceful closure) */ 00041 else if (Status == STATUS_SUCCESS) 00042 { 00043 FCB->Recv.Content = 0; 00044 FCB->TdiReceiveClosed = TRUE; 00045 00046 /* Signal graceful receive shutdown */ 00047 FCB->PollState |= AFD_EVENT_DISCONNECT; 00048 FCB->PollStatus[FD_CLOSE_BIT] = Status; 00049 00050 PollReeval( FCB->DeviceExt, FCB->FileObject ); 00051 } 00052 /* Receive failed with no data (unexpected closure) */ 00053 else 00054 { 00055 FCB->Recv.Content = 0; 00056 FCB->TdiReceiveClosed = TRUE; 00057 00058 /* Signal complete connection failure immediately */ 00059 FCB->PollState |= AFD_EVENT_CLOSE; 00060 FCB->PollStatus[FD_CLOSE_BIT] = Status; 00061 00062 PollReeval( FCB->DeviceExt, FCB->FileObject ); 00063 } 00064 } 00065 00066 static BOOLEAN CantReadMore( PAFD_FCB FCB ) { 00067 UINT BytesAvailable = FCB->Recv.Content - FCB->Recv.BytesUsed; 00068 00069 return !BytesAvailable && FCB->TdiReceiveClosed; 00070 } 00071 00072 static VOID RefillSocketBuffer( PAFD_FCB FCB ) { 00073 if( !FCB->ReceiveIrp.InFlightRequest && 00074 !FCB->TdiReceiveClosed ) { 00075 AFD_DbgPrint(MID_TRACE,("Replenishing buffer\n")); 00076 00077 TdiReceive( &FCB->ReceiveIrp.InFlightRequest, 00078 FCB->Connection.Object, 00079 TDI_RECEIVE_NORMAL, 00080 FCB->Recv.Window, 00081 FCB->Recv.Size, 00082 &FCB->ReceiveIrp.Iosb, 00083 ReceiveComplete, 00084 FCB ); 00085 } 00086 } 00087 00088 static NTSTATUS TryToSatisfyRecvRequestFromBuffer( PAFD_FCB FCB, 00089 PAFD_RECV_INFO RecvReq, 00090 PUINT TotalBytesCopied ) { 00091 UINT i, BytesToCopy = 0, FcbBytesCopied = FCB->Recv.BytesUsed, 00092 BytesAvailable = 00093 FCB->Recv.Content - FCB->Recv.BytesUsed; 00094 PAFD_MAPBUF Map; 00095 *TotalBytesCopied = 0; 00096 00097 00098 AFD_DbgPrint(MID_TRACE,("Called, BytesAvailable = %d\n", 00099 BytesAvailable)); 00100 00101 if( CantReadMore(FCB) ) return STATUS_SUCCESS; 00102 if( !BytesAvailable ) return STATUS_PENDING; 00103 00104 Map = (PAFD_MAPBUF)(RecvReq->BufferArray + RecvReq->BufferCount); 00105 00106 AFD_DbgPrint(MID_TRACE,("Buffer Count: %d @ %x\n", 00107 RecvReq->BufferCount, 00108 RecvReq->BufferArray)); 00109 for( i = 0; 00110 RecvReq->BufferArray && 00111 BytesAvailable && 00112 i < RecvReq->BufferCount; 00113 i++ ) { 00114 BytesToCopy = 00115 MIN( RecvReq->BufferArray[i].len, BytesAvailable ); 00116 00117 if( Map[i].Mdl ) { 00118 Map[i].BufferAddress = MmMapLockedPages( Map[i].Mdl, KernelMode ); 00119 00120 AFD_DbgPrint(MID_TRACE,("Buffer %d: %x:%d\n", 00121 i, 00122 Map[i].BufferAddress, 00123 BytesToCopy)); 00124 00125 RtlCopyMemory( Map[i].BufferAddress, 00126 FCB->Recv.Window + FcbBytesCopied, 00127 BytesToCopy ); 00128 00129 MmUnmapLockedPages( Map[i].BufferAddress, Map[i].Mdl ); 00130 00131 *TotalBytesCopied += BytesToCopy; 00132 FcbBytesCopied += BytesToCopy; 00133 BytesAvailable -= BytesToCopy; 00134 00135 if (!(RecvReq->TdiFlags & TDI_RECEIVE_PEEK)) 00136 FCB->Recv.BytesUsed += BytesToCopy; 00137 } 00138 } 00139 00140 /* If there's nothing left in our buffer start a new request */ 00141 if( FCB->Recv.BytesUsed == FCB->Recv.Content ) { 00142 FCB->Recv.BytesUsed = FCB->Recv.Content = 0; 00143 FCB->PollState &= ~AFD_EVENT_RECEIVE; 00144 00145 RefillSocketBuffer( FCB ); 00146 } 00147 00148 return STATUS_SUCCESS; 00149 } 00150 00151 static NTSTATUS ReceiveActivity( PAFD_FCB FCB, PIRP Irp ) { 00152 PLIST_ENTRY NextIrpEntry; 00153 PIRP NextIrp; 00154 PIO_STACK_LOCATION NextIrpSp; 00155 PAFD_RECV_INFO RecvReq; 00156 UINT TotalBytesCopied = 0, RetBytesCopied = 0; 00157 NTSTATUS Status = STATUS_SUCCESS, RetStatus = STATUS_PENDING; 00158 00159 AFD_DbgPrint(MID_TRACE,("%x %x\n", FCB, Irp)); 00160 00161 /* Kick the user that receive would be possible now */ 00162 /* XXX Not implemented yet */ 00163 00164 AFD_DbgPrint(MID_TRACE,("FCB %x Receive data waiting %d\n", 00165 FCB, FCB->Recv.Content)); 00166 00167 if( CantReadMore( FCB ) ) { 00168 /* Success here means that we got an EOF. Complete a pending read 00169 * with zero bytes if we haven't yet overread, then kill the others. 00170 */ 00171 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) { 00172 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]); 00173 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry); 00174 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp ); 00175 RecvReq = GetLockedData(NextIrp, NextIrpSp); 00176 00177 AFD_DbgPrint(MID_TRACE,("Completing recv %x (%d)\n", NextIrp, 00178 TotalBytesCopied)); 00179 UnlockBuffers( RecvReq->BufferArray, 00180 RecvReq->BufferCount, FALSE ); 00181 if (FCB->Overread && FCB->PollStatus[FD_CLOSE_BIT] == STATUS_SUCCESS) 00182 { 00183 /* Overread after a graceful disconnect so complete with an error */ 00184 Status = STATUS_FILE_CLOSED; 00185 } 00186 else 00187 { 00188 /* Unexpected disconnect by the remote host or initial read after a graceful disconnnect */ 00189 Status = FCB->PollStatus[FD_CLOSE_BIT]; 00190 } 00191 NextIrp->IoStatus.Status = Status; 00192 NextIrp->IoStatus.Information = 0; 00193 if( NextIrp == Irp ) RetStatus = Status; 00194 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); 00195 (void)IoSetCancelRoutine(NextIrp, NULL); 00196 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); 00197 FCB->Overread = TRUE; 00198 } 00199 } else { 00200 /* Kick the user that receive would be possible now */ 00201 /* XXX Not implemented yet */ 00202 00203 AFD_DbgPrint(MID_TRACE,("FCB %x Receive data waiting %d\n", 00204 FCB, FCB->Recv.Content)); 00205 /*OskitDumpBuffer( FCB->Recv.Window, FCB->Recv.Content );*/ 00206 00207 /* Try to clear some requests */ 00208 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) { 00209 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]); 00210 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry); 00211 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp ); 00212 RecvReq = GetLockedData(NextIrp, NextIrpSp); 00213 00214 AFD_DbgPrint(MID_TRACE,("RecvReq @ %x\n", RecvReq)); 00215 00216 Status = TryToSatisfyRecvRequestFromBuffer 00217 ( FCB, RecvReq, &TotalBytesCopied ); 00218 00219 if( Status == STATUS_PENDING ) { 00220 AFD_DbgPrint(MID_TRACE,("Ran out of data for %x\n", NextIrp)); 00221 InsertHeadList(&FCB->PendingIrpList[FUNCTION_RECV], 00222 &NextIrp->Tail.Overlay.ListEntry); 00223 break; 00224 } else { 00225 AFD_DbgPrint(MID_TRACE,("Completing recv %x (%d)\n", NextIrp, 00226 TotalBytesCopied)); 00227 UnlockBuffers( RecvReq->BufferArray, 00228 RecvReq->BufferCount, FALSE ); 00229 NextIrp->IoStatus.Status = Status; 00230 NextIrp->IoStatus.Information = TotalBytesCopied; 00231 if( NextIrp == Irp ) { 00232 RetStatus = Status; 00233 RetBytesCopied = TotalBytesCopied; 00234 } 00235 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); 00236 (void)IoSetCancelRoutine(NextIrp, NULL); 00237 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); 00238 } 00239 } 00240 } 00241 00242 if( FCB->Recv.Content - FCB->Recv.BytesUsed && 00243 IsListEmpty(&FCB->PendingIrpList[FUNCTION_RECV]) ) { 00244 FCB->PollState |= AFD_EVENT_RECEIVE; 00245 FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS; 00246 PollReeval( FCB->DeviceExt, FCB->FileObject ); 00247 } 00248 else 00249 { 00250 FCB->PollState &= ~AFD_EVENT_RECEIVE; 00251 } 00252 00253 AFD_DbgPrint(MID_TRACE,("RetStatus for irp %x is %x\n", Irp, RetStatus)); 00254 00255 /* Sometimes we're called with a NULL Irp */ 00256 if( Irp ) { 00257 Irp->IoStatus.Status = RetStatus; 00258 Irp->IoStatus.Information = RetBytesCopied; 00259 } 00260 00261 return RetStatus; 00262 } 00263 00264 NTSTATUS NTAPI ReceiveComplete 00265 ( PDEVICE_OBJECT DeviceObject, 00266 PIRP Irp, 00267 PVOID Context ) { 00268 PAFD_FCB FCB = (PAFD_FCB)Context; 00269 PLIST_ENTRY NextIrpEntry; 00270 PIRP NextIrp; 00271 PAFD_RECV_INFO RecvReq; 00272 PIO_STACK_LOCATION NextIrpSp; 00273 00274 AFD_DbgPrint(MID_TRACE,("Called\n")); 00275 00276 if( !SocketAcquireStateLock( FCB ) ) 00277 return STATUS_FILE_CLOSED; 00278 00279 ASSERT(FCB->ReceiveIrp.InFlightRequest == Irp); 00280 FCB->ReceiveIrp.InFlightRequest = NULL; 00281 00282 if( FCB->State == SOCKET_STATE_CLOSED ) { 00283 /* Cleanup our IRP queue because the FCB is being destroyed */ 00284 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) { 00285 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]); 00286 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry); 00287 NextIrpSp = IoGetCurrentIrpStackLocation(NextIrp); 00288 RecvReq = GetLockedData(NextIrp, NextIrpSp); 00289 NextIrp->IoStatus.Status = STATUS_FILE_CLOSED; 00290 NextIrp->IoStatus.Information = 0; 00291 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE); 00292 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); 00293 (void)IoSetCancelRoutine(NextIrp, NULL); 00294 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); 00295 } 00296 SocketStateUnlock( FCB ); 00297 return STATUS_FILE_CLOSED; 00298 } else if( FCB->State == SOCKET_STATE_LISTENING ) { 00299 AFD_DbgPrint(MIN_TRACE,("!!! LISTENER GOT A RECEIVE COMPLETE !!!\n")); 00300 SocketStateUnlock( FCB ); 00301 return STATUS_INVALID_PARAMETER; 00302 } 00303 00304 HandleReceiveComplete( FCB, Irp->IoStatus.Status, Irp->IoStatus.Information ); 00305 00306 ReceiveActivity( FCB, NULL ); 00307 00308 SocketStateUnlock( FCB ); 00309 00310 return STATUS_SUCCESS; 00311 } 00312 00313 static NTSTATUS NTAPI 00314 SatisfyPacketRecvRequest( PAFD_FCB FCB, PIRP Irp, 00315 PAFD_STORED_DATAGRAM DatagramRecv, 00316 PUINT TotalBytesCopied ) { 00317 NTSTATUS Status = STATUS_SUCCESS; 00318 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); 00319 PAFD_RECV_INFO RecvReq = 00320 GetLockedData(Irp, IrpSp); 00321 UINT BytesToCopy = 0, BytesAvailable = DatagramRecv->Len, AddrLen = 0; 00322 PAFD_MAPBUF Map; 00323 BOOLEAN ExtraBuffers = CheckUnlockExtraBuffers(FCB, IrpSp); 00324 00325 Map = (PAFD_MAPBUF)(RecvReq->BufferArray + 00326 RecvReq->BufferCount + 00327 (ExtraBuffers ? EXTRA_LOCK_BUFFERS : 0)); 00328 00329 BytesToCopy = MIN( RecvReq->BufferArray[0].len, BytesAvailable ); 00330 00331 AFD_DbgPrint(MID_TRACE,("BytesToCopy: %d len %d\n", BytesToCopy, 00332 RecvReq->BufferArray[0].len)); 00333 00334 if( Map[0].Mdl ) { 00335 /* Copy the address */ 00336 if( ExtraBuffers && Map[1].Mdl && Map[2].Mdl ) { 00337 AFD_DbgPrint(MID_TRACE,("Checking TAAddressCount\n")); 00338 00339 if( DatagramRecv->Address->TAAddressCount != 1 ) { 00340 AFD_DbgPrint 00341 (MIN_TRACE, 00342 ("Wierd address count %d\n", 00343 DatagramRecv->Address->TAAddressCount)); 00344 } 00345 00346 AFD_DbgPrint(MID_TRACE,("Computing addr len\n")); 00347 00348 AddrLen = MIN(DatagramRecv->Address->Address->AddressLength + 00349 sizeof(USHORT), 00350 RecvReq->BufferArray[1].len); 00351 00352 AFD_DbgPrint(MID_TRACE,("Copying %d bytes of address\n", AddrLen)); 00353 00354 Map[1].BufferAddress = MmMapLockedPages( Map[1].Mdl, KernelMode ); 00355 00356 AFD_DbgPrint(MID_TRACE,("Done mapping, copying address\n")); 00357 00358 RtlCopyMemory( Map[1].BufferAddress, 00359 &DatagramRecv->Address->Address->AddressType, 00360 AddrLen ); 00361 00362 MmUnmapLockedPages( Map[1].BufferAddress, Map[1].Mdl ); 00363 00364 AFD_DbgPrint(MID_TRACE,("Copying address len\n")); 00365 00366 Map[2].BufferAddress = MmMapLockedPages( Map[2].Mdl, KernelMode ); 00367 *((PINT)Map[2].BufferAddress) = AddrLen; 00368 MmUnmapLockedPages( Map[2].BufferAddress, Map[2].Mdl ); 00369 } 00370 00371 AFD_DbgPrint(MID_TRACE,("Mapping data buffer pages\n")); 00372 00373 Map[0].BufferAddress = MmMapLockedPages( Map[0].Mdl, KernelMode ); 00374 00375 AFD_DbgPrint(MID_TRACE,("Buffer %d: %x:%d\n", 00376 0, 00377 Map[0].BufferAddress, 00378 BytesToCopy)); 00379 00380 RtlCopyMemory( Map[0].BufferAddress, 00381 DatagramRecv->Buffer, 00382 BytesToCopy ); 00383 00384 MmUnmapLockedPages( Map[0].BufferAddress, Map[0].Mdl ); 00385 00386 *TotalBytesCopied = BytesToCopy; 00387 } 00388 00389 if (*TotalBytesCopied == DatagramRecv->Len) 00390 { 00391 /* We copied the whole datagram */ 00392 Status = Irp->IoStatus.Status = STATUS_SUCCESS; 00393 } 00394 else 00395 { 00396 /* We only copied part of the datagram */ 00397 Status = Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW; 00398 } 00399 00400 Irp->IoStatus.Information = *TotalBytesCopied; 00401 00402 if (!(RecvReq->TdiFlags & TDI_RECEIVE_PEEK)) 00403 { 00404 FCB->Recv.Content -= *TotalBytesCopied; 00405 ExFreePool( DatagramRecv->Address ); 00406 ExFreePool( DatagramRecv ); 00407 } 00408 00409 AFD_DbgPrint(MID_TRACE,("Done\n")); 00410 00411 return Status; 00412 } 00413 00414 NTSTATUS NTAPI 00415 AfdConnectedSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp, 00416 PIO_STACK_LOCATION IrpSp, BOOLEAN Short) { 00417 NTSTATUS Status = STATUS_INVALID_PARAMETER; 00418 PFILE_OBJECT FileObject = IrpSp->FileObject; 00419 PAFD_FCB FCB = FileObject->FsContext; 00420 PAFD_RECV_INFO RecvReq; 00421 UINT TotalBytesCopied = 0; 00422 PAFD_STORED_DATAGRAM DatagramRecv; 00423 PLIST_ENTRY ListEntry; 00424 00425 AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB)); 00426 00427 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp ); 00428 00429 if( !(FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS) && 00430 FCB->State != SOCKET_STATE_CONNECTED && 00431 FCB->State != SOCKET_STATE_CONNECTING ) { 00432 AFD_DbgPrint(MIN_TRACE,("Called recv on wrong kind of socket (s%x)\n", 00433 FCB->State)); 00434 return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER, 00435 Irp, 0 ); 00436 } 00437 00438 if( !(RecvReq = LockRequest( Irp, IrpSp )) ) 00439 return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, 00440 Irp, 0 ); 00441 00442 AFD_DbgPrint(MID_TRACE,("Recv flags %x\n", RecvReq->AfdFlags)); 00443 00444 RecvReq->BufferArray = LockBuffers( RecvReq->BufferArray, 00445 RecvReq->BufferCount, 00446 NULL, NULL, 00447 TRUE, FALSE ); 00448 00449 if( !RecvReq->BufferArray ) { 00450 return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION, 00451 Irp, 0 ); 00452 } 00453 00454 FCB->EventSelectDisabled &= ~AFD_EVENT_RECEIVE; 00455 00456 if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS ) 00457 { 00458 if (!IsListEmpty(&FCB->DatagramList)) 00459 { 00460 ListEntry = RemoveHeadList(&FCB->DatagramList); 00461 DatagramRecv = CONTAINING_RECORD(ListEntry, AFD_STORED_DATAGRAM, ListEntry); 00462 Status = SatisfyPacketRecvRequest(FCB, Irp, DatagramRecv, 00463 (PUINT)&Irp->IoStatus.Information); 00464 00465 if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK) 00466 { 00467 InsertHeadList(&FCB->DatagramList, 00468 &DatagramRecv->ListEntry); 00469 } 00470 00471 if (!IsListEmpty(&FCB->DatagramList)) 00472 { 00473 FCB->PollState |= AFD_EVENT_RECEIVE; 00474 FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS; 00475 PollReeval( FCB->DeviceExt, FCB->FileObject ); 00476 } 00477 else 00478 FCB->PollState &= ~AFD_EVENT_RECEIVE; 00479 00480 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE); 00481 00482 return UnlockAndMaybeComplete(FCB, Status, Irp, Irp->IoStatus.Information); 00483 } 00484 else if( (RecvReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking) ) 00485 { 00486 AFD_DbgPrint(MID_TRACE,("Nonblocking\n")); 00487 Status = STATUS_CANT_WAIT; 00488 FCB->PollState &= ~AFD_EVENT_RECEIVE; 00489 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, FALSE ); 00490 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); 00491 } 00492 else 00493 { 00494 FCB->PollState &= ~AFD_EVENT_RECEIVE; 00495 return LeaveIrpUntilLater( FCB, Irp, FUNCTION_RECV ); 00496 } 00497 } 00498 00499 Irp->IoStatus.Status = STATUS_PENDING; 00500 Irp->IoStatus.Information = 0; 00501 00502 InsertTailList( &FCB->PendingIrpList[FUNCTION_RECV], 00503 &Irp->Tail.Overlay.ListEntry ); 00504 00505 /************ From this point, the IRP is not ours ************/ 00506 00507 Status = ReceiveActivity( FCB, Irp ); 00508 00509 if( Status == STATUS_PENDING && 00510 ((RecvReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking)) ) { 00511 AFD_DbgPrint(MID_TRACE,("Nonblocking\n")); 00512 Status = STATUS_CANT_WAIT; 00513 TotalBytesCopied = 0; 00514 RemoveEntryList( &Irp->Tail.Overlay.ListEntry ); 00515 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, FALSE ); 00516 return UnlockAndMaybeComplete( FCB, Status, Irp, 00517 TotalBytesCopied ); 00518 } else if( Status == STATUS_PENDING ) { 00519 AFD_DbgPrint(MID_TRACE,("Leaving read irp\n")); 00520 IoMarkIrpPending( Irp ); 00521 (void)IoSetCancelRoutine(Irp, AfdCancelHandler); 00522 } else { 00523 AFD_DbgPrint(MID_TRACE,("Completed with status %x\n", Status)); 00524 } 00525 00526 SocketStateUnlock( FCB ); 00527 return Status; 00528 } 00529 00530 NTSTATUS NTAPI 00531 PacketSocketRecvComplete( 00532 PDEVICE_OBJECT DeviceObject, 00533 PIRP Irp, 00534 PVOID Context ) { 00535 NTSTATUS Status = STATUS_SUCCESS; 00536 PAFD_FCB FCB = Context; 00537 PIRP NextIrp; 00538 PIO_STACK_LOCATION NextIrpSp; 00539 PLIST_ENTRY ListEntry; 00540 PAFD_RECV_INFO RecvReq; 00541 PAFD_STORED_DATAGRAM DatagramRecv; 00542 UINT DGSize = Irp->IoStatus.Information + sizeof( AFD_STORED_DATAGRAM ); 00543 PLIST_ENTRY NextIrpEntry, DatagramRecvEntry; 00544 00545 AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB)); 00546 00547 if( !SocketAcquireStateLock( FCB ) ) 00548 return STATUS_FILE_CLOSED; 00549 00550 ASSERT(FCB->ReceiveIrp.InFlightRequest == Irp); 00551 FCB->ReceiveIrp.InFlightRequest = NULL; 00552 00553 if( FCB->State == SOCKET_STATE_CLOSED ) { 00554 /* Cleanup our IRP queue because the FCB is being destroyed */ 00555 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) { 00556 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]); 00557 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry); 00558 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp ); 00559 RecvReq = GetLockedData(NextIrp, NextIrpSp); 00560 NextIrp->IoStatus.Status = STATUS_FILE_CLOSED; 00561 NextIrp->IoStatus.Information = 0; 00562 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, CheckUnlockExtraBuffers(FCB, NextIrpSp)); 00563 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); 00564 (void)IoSetCancelRoutine(NextIrp, NULL); 00565 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); 00566 } 00567 00568 /* Free all items on the datagram list */ 00569 while( !IsListEmpty( &FCB->DatagramList ) ) { 00570 DatagramRecvEntry = RemoveHeadList(&FCB->DatagramList); 00571 DatagramRecv = CONTAINING_RECORD(DatagramRecvEntry, AFD_STORED_DATAGRAM, ListEntry); 00572 ExFreePool( DatagramRecv->Address ); 00573 ExFreePool( DatagramRecv ); 00574 } 00575 00576 SocketStateUnlock( FCB ); 00577 return STATUS_FILE_CLOSED; 00578 } 00579 00580 if (Irp->IoStatus.Status != STATUS_SUCCESS) 00581 { 00582 SocketStateUnlock(FCB); 00583 return Irp->IoStatus.Status; 00584 } 00585 00586 if (FCB->TdiReceiveClosed) 00587 { 00588 SocketStateUnlock(FCB); 00589 return STATUS_FILE_CLOSED; 00590 } 00591 00592 DatagramRecv = ExAllocatePool( NonPagedPool, DGSize ); 00593 00594 if( DatagramRecv ) { 00595 DatagramRecv->Len = Irp->IoStatus.Information; 00596 RtlCopyMemory( DatagramRecv->Buffer, FCB->Recv.Window, 00597 DatagramRecv->Len ); 00598 AFD_DbgPrint(MID_TRACE,("Received (A %x)\n", 00599 FCB->AddressFrom->RemoteAddress)); 00600 DatagramRecv->Address = 00601 TaCopyTransportAddress( FCB->AddressFrom->RemoteAddress ); 00602 00603 if( !DatagramRecv->Address ) Status = STATUS_NO_MEMORY; 00604 00605 } else Status = STATUS_NO_MEMORY; 00606 00607 if( !NT_SUCCESS( Status ) ) { 00608 if( DatagramRecv ) ExFreePool( DatagramRecv ); 00609 SocketStateUnlock( FCB ); 00610 return Status; 00611 } else { 00612 FCB->Recv.Content += DatagramRecv->Len; 00613 InsertTailList( &FCB->DatagramList, &DatagramRecv->ListEntry ); 00614 } 00615 00616 /* Satisfy as many requests as we can */ 00617 00618 while( !IsListEmpty( &FCB->DatagramList ) && 00619 !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) { 00620 AFD_DbgPrint(MID_TRACE,("Looping trying to satisfy request\n")); 00621 ListEntry = RemoveHeadList( &FCB->DatagramList ); 00622 DatagramRecv = CONTAINING_RECORD( ListEntry, AFD_STORED_DATAGRAM, 00623 ListEntry ); 00624 ListEntry = RemoveHeadList( &FCB->PendingIrpList[FUNCTION_RECV] ); 00625 NextIrp = CONTAINING_RECORD( ListEntry, IRP, Tail.Overlay.ListEntry ); 00626 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp ); 00627 RecvReq = GetLockedData(NextIrp, NextIrpSp); 00628 00629 AFD_DbgPrint(MID_TRACE,("RecvReq: %x, DatagramRecv: %x\n", 00630 RecvReq, DatagramRecv)); 00631 00632 AFD_DbgPrint(MID_TRACE,("Satisfying\n")); 00633 Status = SatisfyPacketRecvRequest 00634 ( FCB, NextIrp, DatagramRecv, 00635 (PUINT)&NextIrp->IoStatus.Information ); 00636 00637 if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK) 00638 { 00639 InsertHeadList(&FCB->DatagramList, 00640 &DatagramRecv->ListEntry); 00641 } 00642 00643 AFD_DbgPrint(MID_TRACE,("Unlocking\n")); 00644 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, CheckUnlockExtraBuffers(FCB, NextIrpSp) ); 00645 if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); 00646 00647 AFD_DbgPrint(MID_TRACE,("Completing\n")); 00648 (void)IoSetCancelRoutine(NextIrp, NULL); 00649 NextIrp->IoStatus.Status = Status; 00650 00651 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); 00652 } 00653 00654 if( !IsListEmpty( &FCB->DatagramList ) && IsListEmpty(&FCB->PendingIrpList[FUNCTION_RECV]) ) { 00655 AFD_DbgPrint(MID_TRACE,("Signalling\n")); 00656 FCB->PollState |= AFD_EVENT_RECEIVE; 00657 FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS; 00658 PollReeval( FCB->DeviceExt, FCB->FileObject ); 00659 } else 00660 FCB->PollState &= ~AFD_EVENT_RECEIVE; 00661 00662 if( NT_SUCCESS(Irp->IoStatus.Status) ) { 00663 /* Now relaunch the datagram request */ 00664 Status = TdiReceiveDatagram 00665 ( &FCB->ReceiveIrp.InFlightRequest, 00666 FCB->AddressFile.Object, 00667 0, 00668 FCB->Recv.Window, 00669 FCB->Recv.Size, 00670 FCB->AddressFrom, 00671 &FCB->ReceiveIrp.Iosb, 00672 PacketSocketRecvComplete, 00673 FCB ); 00674 } 00675 00676 SocketStateUnlock( FCB ); 00677 00678 return STATUS_SUCCESS; 00679 } 00680 00681 NTSTATUS NTAPI 00682 AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp, 00683 PIO_STACK_LOCATION IrpSp ) { 00684 NTSTATUS Status = STATUS_SUCCESS; 00685 PFILE_OBJECT FileObject = IrpSp->FileObject; 00686 PAFD_FCB FCB = FileObject->FsContext; 00687 PAFD_RECV_INFO_UDP RecvReq; 00688 PLIST_ENTRY ListEntry; 00689 PAFD_STORED_DATAGRAM DatagramRecv; 00690 00691 AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB)); 00692 00693 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp ); 00694 00695 /* Check that the socket is bound */ 00696 if( FCB->State != SOCKET_STATE_BOUND ) 00697 { 00698 AFD_DbgPrint(MIN_TRACE,("Invalid socket state\n")); 00699 return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0); 00700 } 00701 00702 if (FCB->TdiReceiveClosed) 00703 { 00704 AFD_DbgPrint(MIN_TRACE,("Receive closed\n")); 00705 return UnlockAndMaybeComplete(FCB, STATUS_FILE_CLOSED, Irp, 0); 00706 } 00707 00708 if( !(RecvReq = LockRequest( Irp, IrpSp )) ) 00709 return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0); 00710 00711 AFD_DbgPrint(MID_TRACE,("Recv flags %x\n", RecvReq->AfdFlags)); 00712 00713 RecvReq->BufferArray = LockBuffers( RecvReq->BufferArray, 00714 RecvReq->BufferCount, 00715 RecvReq->Address, 00716 RecvReq->AddressLength, 00717 TRUE, TRUE ); 00718 00719 if( !RecvReq->BufferArray ) { /* access violation in userspace */ 00720 return UnlockAndMaybeComplete(FCB, STATUS_ACCESS_VIOLATION, Irp, 0); 00721 } 00722 00723 FCB->EventSelectDisabled &= ~AFD_EVENT_RECEIVE; 00724 00725 if (!IsListEmpty(&FCB->DatagramList)) 00726 { 00727 ListEntry = RemoveHeadList(&FCB->DatagramList); 00728 DatagramRecv = CONTAINING_RECORD(ListEntry, AFD_STORED_DATAGRAM, ListEntry); 00729 Status = SatisfyPacketRecvRequest(FCB, Irp, DatagramRecv, 00730 (PUINT)&Irp->IoStatus.Information); 00731 00732 if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK) 00733 { 00734 InsertHeadList(&FCB->DatagramList, 00735 &DatagramRecv->ListEntry); 00736 } 00737 00738 if (!IsListEmpty(&FCB->DatagramList)) 00739 { 00740 FCB->PollState |= AFD_EVENT_RECEIVE; 00741 FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS; 00742 PollReeval( FCB->DeviceExt, FCB->FileObject ); 00743 } 00744 else 00745 FCB->PollState &= ~AFD_EVENT_RECEIVE; 00746 00747 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, TRUE); 00748 00749 return UnlockAndMaybeComplete(FCB, Status, Irp, Irp->IoStatus.Information); 00750 } 00751 else if( (RecvReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking) ) 00752 { 00753 AFD_DbgPrint(MID_TRACE,("Nonblocking\n")); 00754 Status = STATUS_CANT_WAIT; 00755 FCB->PollState &= ~AFD_EVENT_RECEIVE; 00756 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE ); 00757 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); 00758 } 00759 else 00760 { 00761 FCB->PollState &= ~AFD_EVENT_RECEIVE; 00762 return LeaveIrpUntilLater( FCB, Irp, FUNCTION_RECV ); 00763 } 00764 } Generated on Sun May 27 2012 04:27:44 for ReactOS by
1.7.6.1
|