ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

read.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.