VOID NdisProtCancelWrite( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp ) /*++ Routine Description: Cancel a pending write IRP. This routine attempt to cancel the NDIS send. Arguments: pDeviceObject - pointer to our device object pIrp - IRP to be cancelled Return Value: None --*/ { PNDISPROT_OPEN_CONTEXT pOpenContext; PLIST_ENTRY pIrpEntry; PNDIS_PACKET pNdisPacket; UNREFERENCED_PARAMETER(pDeviceObject); IoReleaseCancelSpinLock(pIrp->CancelIrql); // // The NDIS packet representing this Write IRP. // pNdisPacket = NULL; pOpenContext = (PNDISPROT_OPEN_CONTEXT) pIrp->Tail.Overlay.DriverContext[0]; NPROT_STRUCT_ASSERT(pOpenContext, oc); // // Try to locate the IRP in the pended write queue. The send completion // routine may be running and might have removed it from there. // NPROT_ACQUIRE_LOCK(&pOpenContext->Lock); for (pIrpEntry = pOpenContext->PendedWrites.Flink; pIrpEntry != &pOpenContext->PendedWrites; pIrpEntry = pIrpEntry->Flink) { if (pIrp == CONTAINING_RECORD(pIrpEntry, IRP, Tail.Overlay.ListEntry)) { pNdisPacket = (PNDIS_PACKET) pIrp->Tail.Overlay.DriverContext[1]; // // Place a reference on this packet so that it won't get // freed/reused until we are done with it. // NPROT_REF_SEND_PKT(pNdisPacket); break; } } NPROT_RELEASE_LOCK(&pOpenContext->Lock); if (pNdisPacket != NULL) { // // Either the send completion routine hasn't run, or we got a peak // at the IRP/packet before it had a chance to take it out of the // pending IRP queue. // // We do not complete the IRP here - note that we didn't dequeue it // above. This is because we always want the send complete routine to // complete the IRP. And this in turn is because the packet that was // prepared from the IRP has a buffer chain pointing to data associated // with this IRP. Therefore we cannot complete the IRP before the driver // below us is done with the data it pointed to. // // // Request NDIS to cancel this send. The result of this call is that // our SendComplete handler will be called (if not already called). // DEBUGP(DL_INFO, ("CancelWrite: cancelling pkt %p on Open %p\n", pNdisPacket, pOpenContext)); NdisCancelSendPackets( pOpenContext->BindingHandle, NDIS_GET_PACKET_CANCEL_ID(pNdisPacket) ); // // It is now safe to remove the reference we had placed on the packet. // NPROT_DEREF_SEND_PKT(pNdisPacket); } // // else the send completion routine has already picked up this IRP. // }
VOID SecLabCancelWrite( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp ) /*++ Routine Description: Cancel a pending write IRP. This routine attempt to cancel the NDIS send. Arguments: pDeviceObject - pointer to our device object pIrp - IRP to be cancelled Return Value: None --*/ { PADAPT pAdapt; PLIST_ENTRY pIrpEntry; PNDIS_PACKET pNdisPacket; IoReleaseCancelSpinLock(pIrp->CancelIrql); // // 一个封包代表一个写IRP. // pNdisPacket = NULL; pAdapt = (PADAPT) pIrp->Tail.Overlay.DriverContext[0]; if(pAdapt==NULL) { DbgPrint("The Adapt handle is NULL"); DbgBreakPoint(); } DbgPrint("once enter the cancel routain"); // // 在写IRP阻塞队列中定位要取消的IRP. 发送完成例程可能已经运行并将其释放 // NdisAcquireSpinLock(&WriteIrpLock); for (pIrpEntry = PendedWritesList.Flink; pIrpEntry != &PendedWritesList; pIrpEntry = pIrpEntry->Flink) { if (pIrp == CONTAINING_RECORD(pIrpEntry, IRP, Tail.Overlay.ListEntry)) { pNdisPacket = (PNDIS_PACKET) pIrp->Tail.Overlay.DriverContext[1]; // // 将此等待IRP代表的封包结构中的RefCount置1.这样在它 // 完成之前就不会被释放或重用了 // SECLAB_REF_SEND_PKT(pNdisPacket); break; } } NdisReleaseSpinLock(&WriteIrpLock); if (pNdisPacket != NULL) { // // Either the send completion routine hasn't run, or we got a peak // at the IRP/packet before it had a chance to take it out of the // pending IRP queue. // // We do not complete the IRP here - note that we didn't dequeue it // above. This is because we always want the send complete routine to // complete the IRP. And this in turn is because the packet that was // prepared from the IRP has a buffer chain pointing to data associated // with this IRP. Therefore we cannot complete the IRP before the driver // below us is done with the data it pointed to. // // // Request NDIS to cancel this send. The result of this call is that // our SendComplete handler will be called (if not already called). // NdisCancelSendPackets( pAdapt->BindingHandle, NDIS_GET_PACKET_CANCEL_ID(pNdisPacket) ); // // It is now safe to remove the reference we had placed on the packet. // SECLAB_DEREF_SEND_PKT(pNdisPacket); } // // else the send completion routine has already picked up this IRP. // }