NTSTATUS LpxTdiReceive( IN PIRP Irp ) /*++ Routine Description: This routine performs the TdiReceive request for the transport provider. Arguments: Irp - I/O Request Packet for this request. Return Value: NTSTATUS - status of operation. --*/ { PTP_CONNECTION connection; PIO_STACK_LOCATION irpSp; // // verify that the operation is taking place on a connection. At the same // time we do this, we reference the connection. This ensures it does not // get removed out from under us. Note also that we do the connection // lookup within a try/except clause, thus protecting ourselves against // really bogus handles // irpSp = IoGetCurrentIrpStackLocation (Irp); connection = irpSp->FileObject->FsContext; IF_LPXDBG (LPX_DEBUG_RCVENG) { LpxPrint2 ("LpxTdiReceive: Received IRP %p on connection %p\n", Irp, connection); } // // Check that this is really a connection. // if ((irpSp->FileObject->FsContext2 == UlongToPtr(LPX_FILE_TYPE_CONTROL)) || (connection->Size != sizeof (TP_CONNECTION)) || (connection->Type != LPX_CONNECTION_SIGNATURE)) { #if DBG LpxPrint2 ("TdiReceive: Invalid Connection %p Irp %p\n", connection, Irp); #endif return STATUS_INVALID_CONNECTION; } #if __LPX__ return LpxRecv( connection, Irp ); #endif } /* TdiReceive */
NTSTATUS NbfTdiReceive( IN PIRP Irp ) /*++ Routine Description: This routine performs the TdiReceive request for the transport provider. Arguments: Irp - I/O Request Packet for this request. Return Value: NTSTATUS - status of operation. --*/ { #ifdef __NBF__ NTSTATUS status; #endif PTP_CONNECTION connection; #ifdef __NBF__ KIRQL oldirql; #endif PIO_STACK_LOCATION irpSp; // // verify that the operation is taking place on a connection. At the same // time we do this, we reference the connection. This ensures it does not // get removed out from under us. Note also that we do the connection // lookup within a try/except clause, thus protecting ourselves against // really bogus handles // irpSp = IoGetCurrentIrpStackLocation (Irp); connection = irpSp->FileObject->FsContext; IF_NBFDBG (NBF_DEBUG_RCVENG) { NbfPrint2 ("NbfTdiReceive: Received IRP %lx on connection %lx\n", Irp, connection); } // // Check that this is really a connection. // if ((irpSp->FileObject->FsContext2 == UlongToPtr(NBF_FILE_TYPE_CONTROL)) || (connection->Size != sizeof (TP_CONNECTION)) || (connection->Type != NBF_CONNECTION_SIGNATURE)) { #if DBG NbfPrint2 ("TdiReceive: Invalid Connection %lx Irp %lx\n", connection, Irp); #endif return STATUS_INVALID_CONNECTION; } #ifdef __LPX__ return LpxRecv( connection, Irp ); #endif #ifdef __NBF__ // // Initialize bytes transferred here. // Irp->IoStatus.Information = 0; // reset byte transfer count. // This reference is removed by NbfDestroyRequest. KeRaiseIrql (DISPATCH_LEVEL, &oldirql); ACQUIRE_DPC_C_SPIN_LOCK (&connection->SpinLock); if ((connection->Flags & CONNECTION_FLAGS_READY) == 0) { RELEASE_DPC_C_SPIN_LOCK (&connection->SpinLock); Irp->IoStatus.Status = connection->Status; IoCompleteRequest (Irp, IO_NETWORK_INCREMENT); status = STATUS_PENDING; } else { KIRQL cancelIrql; // // Once the reference is in, LinkSpinLock will be valid. // NbfReferenceConnection("TdiReceive request", connection, CREF_RECEIVE_IRP); RELEASE_DPC_C_SPIN_LOCK (&connection->SpinLock); IoAcquireCancelSpinLock(&cancelIrql); ACQUIRE_DPC_SPIN_LOCK (connection->LinkSpinLock); IRP_RECEIVE_IRP(irpSp) = Irp; IRP_RECEIVE_REFCOUNT(irpSp) = 1; #if DBG NbfReceives[NbfReceivesNext].Irp = Irp; NbfReceives[NbfReceivesNext].Request = NULL; NbfReceives[NbfReceivesNext].Connection = (PVOID)connection; NbfReceivesNext = (NbfReceivesNext++) % TRACK_TDI_LIMIT; #endif // // If this IRP has been cancelled, complete it now. // if (Irp->Cancel) { #if DBG NbfCompletedReceives[NbfCompletedReceivesNext].Irp = Irp; NbfCompletedReceives[NbfCompletedReceivesNext].Request = NULL; NbfCompletedReceives[NbfCompletedReceivesNext].Status = STATUS_CANCELLED; { ULONG i,j,k; PUCHAR va; PMDL mdl; mdl = Irp->MdlAddress; NbfCompletedReceives[NbfCompletedReceivesNext].Contents[0] = (UCHAR)0; i = 1; while (i<TRACK_TDI_CAPTURE) { if (mdl == NULL) break; va = MmGetSystemAddressForMdl (mdl); j = MmGetMdlByteCount (mdl); for (i=i,k=0; (i<TRACK_TDI_CAPTURE)&&(k<j); i++,k++) { NbfCompletedReceives[NbfCompletedReceivesNext].Contents[i] = *va++; } mdl = mdl->Next; } } NbfCompletedReceivesNext = (NbfCompletedReceivesNext++) % TRACK_TDI_LIMIT; #endif // // It is safe to do this with locks held. // NbfCompleteReceiveIrp (Irp, STATUS_CANCELLED, 0); RELEASE_DPC_SPIN_LOCK (connection->LinkSpinLock); IoReleaseCancelSpinLock(cancelIrql); } else { // // Insert onto the receive queue, and make the IRP // cancellable. // InsertTailList (&connection->ReceiveQueue,&Irp->Tail.Overlay.ListEntry); IoSetCancelRoutine(Irp, NbfCancelReceive); // // Release the cancel spinlock out of order. Since we were // already at dpc level when it was acquired, we don't // need to swap irqls. // ASSERT(cancelIrql == DISPATCH_LEVEL); IoReleaseCancelSpinLock(cancelIrql); // // This call releases the link spinlock, and references the // connection first if it needs to access it after // releasing the lock. // AwakenReceive (connection); // awaken if sleeping. } status = STATUS_PENDING; } KeLowerIrql (oldirql); return status; #endif } /* TdiReceive */