NTSTATUS EVhdNotifyRecoveryStatus(ParserInstance *parser, RecoveryStatusCompletionRoutine pfnCompletionCb, void *pInterface) { PDEVICE_OBJECT pDeviceObject = NULL; if (parser->bResiliencyEnabled) { if (!ExAcquireRundownProtection(&parser->RecoveryRundownProtection)) return STATUS_UNSUCCESSFUL; parser->pfnRecoveryStatusCallback = pfnCompletionCb; parser->pRecoveryStatusInterface = pInterface; IoReuseIrp(parser->pRecoveryStatusIrp, STATUS_PENDING); parser->pRecoveryStatusIrp->Tail.Overlay.Thread = (PETHREAD)__readgsqword(0x188); // Pointer to calling thread control block PIO_STACK_LOCATION pStackFrame = IoGetNextIrpStackLocation(parser->pRecoveryStatusIrp); pDeviceObject = IoGetRelatedDeviceObject(parser->pVhdmpFileObject); pStackFrame->FileObject = parser->pVhdmpFileObject; pStackFrame->DeviceObject = pDeviceObject; pStackFrame->Parameters.DeviceIoControl.IoControlCode = IOCTL_STORAGE_VHD_NOTIFY_RECOVERY_STATUS; pStackFrame->Parameters.DeviceIoControl.InputBufferLength = 0; pStackFrame->Parameters.DeviceIoControl.OutputBufferLength = 0; pStackFrame->MajorFunction = IRP_MJ_DEVICE_CONTROL; pStackFrame->MinorFunction = 0; pStackFrame->Flags = 0; pStackFrame->Control = SL_INVOKE_ON_CANCEL | SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_ERROR; pStackFrame->Context = parser; pStackFrame->CompletionRoutine = EvhdRecoveryStatusCompletionRoutine; IoCallDriver(pDeviceObject, parser->pRecoveryStatusIrp); return STATUS_PENDING; } else return STATUS_UNSUCCESSFUL; }
static NTSTATUS EvhdDirectIoControl(ParserInstance *parser, ULONG ControlCode, PVOID pSystemBuffer, ULONG InputBufferSize, ULONG OutputBufferSize) { NTSTATUS status = STATUS_SUCCESS; PDEVICE_OBJECT pDeviceObject = NULL; KeEnterCriticalRegion(); FltAcquirePushLockExclusive(&parser->DirectIoPushLock); IoReuseIrp(parser->pDirectIoIrp, STATUS_PENDING); parser->pDirectIoIrp->Flags |= IRP_NOCACHE; parser->pDirectIoIrp->Tail.Overlay.Thread = (PETHREAD)__readgsqword(0x188); // Pointer to calling thread control block parser->pDirectIoIrp->AssociatedIrp.SystemBuffer = pSystemBuffer; // IO buffer for buffered control code // fill stack frame parameters for synchronous IRP call PIO_STACK_LOCATION pStackFrame = IoGetNextIrpStackLocation(parser->pDirectIoIrp); pDeviceObject = IoGetRelatedDeviceObject(parser->pVhdmpFileObject); pStackFrame->FileObject = parser->pVhdmpFileObject; pStackFrame->DeviceObject = pDeviceObject; pStackFrame->Parameters.DeviceIoControl.IoControlCode = ControlCode; pStackFrame->Parameters.DeviceIoControl.InputBufferLength = InputBufferSize; pStackFrame->Parameters.DeviceIoControl.OutputBufferLength = OutputBufferSize; pStackFrame->MajorFunction = IRP_MJ_DEVICE_CONTROL; pStackFrame->MinorFunction = 0; pStackFrame->Flags = 0; pStackFrame->Control = 0; IoSynchronousCallDriver(pDeviceObject, parser->pDirectIoIrp); status = parser->pDirectIoIrp->IoStatus.Status; FltReleasePushLock(&parser->DirectIoPushLock); KeLeaveCriticalRegion(); return status; }
NTSTATUS EVhdGetQosStatusDisk(ParserInstance *parser, PVOID pSystemBuffer, ULONG32 dwSize, QoSStatusCompletionRoutine pfnCompletionCb, PVOID pInterface) { PDEVICE_OBJECT pDeviceObject = NULL; parser->pQoSStatusInterface = pInterface; parser->pfnQoSStatusCallback = pfnCompletionCb; memmove(parser->pQoSStatusBuffer, pSystemBuffer, dwSize); IoReuseIrp(parser->pQoSStatusIrp, STATUS_PENDING); parser->pQoSStatusIrp->Tail.Overlay.Thread = (PETHREAD)__readgsqword(0x188); // Pointer to calling thread control block parser->pQoSStatusIrp->AssociatedIrp.SystemBuffer = parser->pQoSStatusBuffer; // IO buffer for buffered control code PIO_STACK_LOCATION pStackFrame = IoGetNextIrpStackLocation(parser->pQoSStatusIrp); pDeviceObject = IoGetRelatedDeviceObject(parser->pVhdmpFileObject); pStackFrame->FileObject = parser->pVhdmpFileObject; pStackFrame->DeviceObject = pDeviceObject; pStackFrame->Parameters.DeviceIoControl.IoControlCode = IOCTL_STORAGE_VHD_GET_QOS_STATUS; pStackFrame->Parameters.DeviceIoControl.InputBufferLength = dwSize; pStackFrame->Parameters.DeviceIoControl.OutputBufferLength = 0x58; pStackFrame->MajorFunction = IRP_MJ_DEVICE_CONTROL; pStackFrame->MinorFunction = 0; pStackFrame->Flags = 0; pStackFrame->Control = SL_INVOKE_ON_CANCEL | SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_ERROR; pStackFrame->Context = parser; pStackFrame->CompletionRoutine = EvhdGetQosStatusCompletionRoutine; IoCallDriver(pDeviceObject, parser->pQoSStatusIrp); return STATUS_PENDING; }
FORCEINLINE VOID FxIrp::Reuse( __in NTSTATUS Status ) { IoReuseIrp(m_Irp, Status); }
VOID LspDataReset( __in PDEVICE_OBJECT DeviceObject, __in PLSP_TRANSFER_DATA LspTransferData) { RtlZeroMemory(&LspTransferData->Overlapped, sizeof(XTDI_OVERLAPPED)); LspTransferData->Overlapped.CompletionRoutine = LspTransferCompletion; LspTransferData->Overlapped.UserContext = DeviceObject; LspTransferData->Flags = 0; ASSERT(NULL != LspTransferData->Irp); // IoFreeIrp(LspTransferData->Irp); // LspTransferData->Irp = IoAllocateIrp(DeviceObject->StackSize + 1, FALSE); IoReuseIrp(LspTransferData->Irp, STATUS_SUCCESS); }
VOID ReInitWskData( __out PIRP* pIrp, __out PKEVENT CompletionEvent ) { ASSERT(pIrp); ASSERT(CompletionEvent); KeResetEvent(CompletionEvent); IoReuseIrp(*pIrp, STATUS_UNSUCCESSFUL); IoSetCompletionRoutine(*pIrp, CompletionRoutine, CompletionEvent, TRUE, TRUE, TRUE); return; }
/* * SubmitTransferPacket * * Set up the IRP for the TRANSFER_PACKET submission and send it down. */ VOID SubmitTransferPacket(PTRANSFER_PACKET Pkt) { PCOMMON_DEVICE_EXTENSION commonExtension = Pkt->Fdo->DeviceExtension; PDEVICE_OBJECT nextDevObj = commonExtension->LowerDeviceObject; PIO_STACK_LOCATION nextSp = IoGetNextIrpStackLocation(Pkt->Irp); ASSERT(Pkt->Irp->CurrentLocation == Pkt->Irp->StackCount+1); /* * Attach the SRB to the IRP. * The reused IRP's stack location has to be rewritten for each retry * call because IoCompleteRequest clears the stack locations. */ IoReuseIrp(Pkt->Irp, STATUS_NOT_SUPPORTED); nextSp->MajorFunction = IRP_MJ_SCSI; nextSp->Parameters.Scsi.Srb = &Pkt->Srb; Pkt->Srb.ScsiStatus = Pkt->Srb.SrbStatus = 0; if (Pkt->CompleteOriginalIrpWhenLastPacketCompletes){ /* * Only dereference the "original IRP"'s stack location * if its a real client irp (as opposed to a static irp * we're using just for result status for one of the non-IO scsi commands). * * For read/write, propagate the storage-specific IRP stack location flags * (e.g. SL_OVERRIDE_VERIFY_VOLUME, SL_WRITE_THROUGH). */ PIO_STACK_LOCATION origCurSp = IoGetCurrentIrpStackLocation(Pkt->OriginalIrp); nextSp->Flags = origCurSp->Flags; } /* * Write MDL address to new IRP. In the port driver the SRB DataBuffer * field is used as the actual buffer pointer within the MDL, * so the same MDL can be used for each partial transfer. * This saves having to build a new MDL for each partial transfer. */ Pkt->Irp->MdlAddress = Pkt->OriginalIrp->MdlAddress; IoSetCompletionRoutine(Pkt->Irp, TransferPktComplete, Pkt, TRUE, TRUE, TRUE); IoCallDriver(nextDevObj, Pkt->Irp); }
// for Reusing IRP, first, create IRP outside, and input SendEx's parameter. Irp can be freed in finalize point. LONG NTAPI SendEx( __in PIRP pIrp, __in PWSK_SOCKET WskSocket, __in PVOID Buffer, __in ULONG BufferSize, __in ULONG Flags, __in struct drbd_transport *transport, __in enum drbd_stream stream ) { KEVENT CompletionEvent = { 0 }; WSK_BUF WskBuffer = { 0 }; LONG BytesSent = SOCKET_ERROR; NTSTATUS Status = STATUS_UNSUCCESSFUL; if (g_SocketsState != INITIALIZED || !WskSocket || !Buffer || !pIrp || ((int)BufferSize <= 0)) return SOCKET_ERROR; Status = InitWskBuffer(Buffer, BufferSize, &WskBuffer); if (!NT_SUCCESS(Status)) { return SOCKET_ERROR; } IoReuseIrp(pIrp, STATUS_UNSUCCESSFUL); KeInitializeEvent(&CompletionEvent, SynchronizationEvent, FALSE); IoSetCompletionRoutine(pIrp, CompletionRoutine, &CompletionEvent, TRUE, TRUE, TRUE); Flags |= WSK_FLAG_NODELAY; Status = ((PWSK_PROVIDER_CONNECTION_DISPATCH)WskSocket->Dispatch)->WskSend( WskSocket, &WskBuffer, Flags, pIrp); if (Status == STATUS_PENDING) { KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL); Status = pIrp->IoStatus.Status; } if (NT_SUCCESS(Status)) { BytesSent = (LONG)pIrp->IoStatus.Information; } else { WDRBD_WARN("tx error(%s) wsk(0x%p)\n", GetSockErrorString(pIrp->IoStatus.Status), WskSocket); switch (Status) { case STATUS_IO_TIMEOUT: BytesSent = -EAGAIN; break; case STATUS_INVALID_DEVICE_STATE: BytesSent = -EAGAIN; break; default: BytesSent = -ECONNRESET; break; } } FreeWskBuffer(&WskBuffer); return BytesSent; }
NTSTATUS IrpClose( IN PFILE_OBJECT FileObject) { NTSTATUS ntStatus; IO_STATUS_BLOCK IoStatusBlock; PIRP Irp; KEVENT kEvent; PIO_STACK_LOCATION IrpSp; PDEVICE_OBJECT pBaseDeviceObject = FileObject->Vpb->DeviceObject; if (FileObject->Vpb == 0 || FileObject->Vpb->DeviceObject == NULL) return STATUS_UNSUCCESSFUL; Irp = IoAllocateIrp(FileObject->Vpb->DeviceObject->StackSize, FALSE); if(Irp == NULL) return STATUS_INSUFFICIENT_RESOURCES; KeInitializeEvent(&kEvent, SynchronizationEvent, FALSE); Irp->UserEvent = &kEvent; Irp->UserIosb = &IoStatusBlock; Irp->RequestorMode = KernelMode; Irp->Flags = IRP_CLOSE_OPERATION|IRP_SYNCHRONOUS_API; Irp->Tail.Overlay.Thread = PsGetCurrentThread(); Irp->Tail.Overlay.OriginalFileObject = FileObject; IrpSp = IoGetNextIrpStackLocation(Irp); IrpSp->MajorFunction = IRP_MJ_CLEANUP; IrpSp->FileObject = FileObject; ntStatus = IoCallDriver(pBaseDeviceObject, Irp); if (ntStatus == STATUS_PENDING) KeWaitForSingleObject(&kEvent, Executive, KernelMode, FALSE, NULL); ntStatus = IoStatusBlock.Status; if(!NT_SUCCESS(ntStatus)) { IoFreeIrp(Irp); return ntStatus; } KeClearEvent(&kEvent); IoReuseIrp(Irp , STATUS_SUCCESS); Irp->UserEvent = &kEvent; Irp->UserIosb = &IoStatusBlock; Irp->Tail.Overlay.OriginalFileObject = FileObject; Irp->Tail.Overlay.Thread = PsGetCurrentThread(); Irp->AssociatedIrp.SystemBuffer = (PVOID)NULL; Irp->Flags = IRP_CLOSE_OPERATION|IRP_SYNCHRONOUS_API; IrpSp = IoGetNextIrpStackLocation(Irp); IrpSp->MajorFunction = IRP_MJ_CLOSE; IrpSp->FileObject = FileObject; if (FileObject->Vpb && !(FileObject->Flags & FO_DIRECT_DEVICE_OPEN)) { InterlockedDecrement(&FileObject->Vpb->ReferenceCount); FileObject->Flags |= FO_FILE_OPEN_CANCELLED; } ntStatus = IoCallDriver(pBaseDeviceObject, Irp); if (ntStatus == STATUS_PENDING) KeWaitForSingleObject(&kEvent, Executive, KernelMode, FALSE, NULL); IoFreeIrp(Irp); ntStatus = IoStatusBlock.Status; return ntStatus; }
/* * SubmitTransferPacket * * Set up the IRP for the TRANSFER_PACKET submission and send it down. */ NTSTATUS SubmitTransferPacket(PTRANSFER_PACKET Pkt) { PCOMMON_DEVICE_EXTENSION commonExtension = Pkt->Fdo->DeviceExtension; PDEVICE_OBJECT nextDevObj = commonExtension->LowerDeviceObject; PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Pkt->Fdo->DeviceExtension; PCLASS_PRIVATE_FDO_DATA fdoData = fdoExtension->PrivateFdoData; BOOLEAN idleRequest = FALSE; PIO_STACK_LOCATION nextSp; ASSERT(Pkt->Irp->CurrentLocation == Pkt->Irp->StackCount+1); /* * Attach the SRB to the IRP. * The reused IRP's stack location has to be rewritten for each retry * call because IoCompleteRequest clears the stack locations. */ IoReuseIrp(Pkt->Irp, STATUS_NOT_SUPPORTED); nextSp = IoGetNextIrpStackLocation(Pkt->Irp); nextSp->MajorFunction = IRP_MJ_SCSI; nextSp->Parameters.Scsi.Srb = &Pkt->Srb; Pkt->Srb.ScsiStatus = Pkt->Srb.SrbStatus = 0; Pkt->Srb.SenseInfoBufferLength = sizeof(SENSE_DATA); if (Pkt->CompleteOriginalIrpWhenLastPacketCompletes){ /* * Only dereference the "original IRP"'s stack location * if its a real client irp (as opposed to a static irp * we're using just for result status for one of the non-IO scsi commands). * * For read/write, propagate the storage-specific IRP stack location flags * (e.g. SL_OVERRIDE_VERIFY_VOLUME, SL_WRITE_THROUGH). */ PIO_STACK_LOCATION origCurSp = IoGetCurrentIrpStackLocation(Pkt->OriginalIrp); nextSp->Flags = origCurSp->Flags; } // // If the request is not split, we can use the original IRP MDL. If the // request needs to be split, we need to use a partial MDL. The partial MDL // is needed because more than one driver might be mapping the same MDL // and this causes problems. // if (Pkt->UsePartialMdl == FALSE) { Pkt->Irp->MdlAddress = Pkt->OriginalIrp->MdlAddress; } else { IoBuildPartialMdl(Pkt->OriginalIrp->MdlAddress, Pkt->PartialMdl, Pkt->Srb.DataBuffer, Pkt->Srb.DataTransferLength); Pkt->Irp->MdlAddress = Pkt->PartialMdl; } DBGLOGSENDPACKET(Pkt); HISTORYLOGSENDPACKET(Pkt); // // Set the original irp here for SFIO. // Pkt->Srb.SrbExtension = (PVOID) (Pkt->OriginalIrp); // // No need to lock for IdlePrioritySupported, since it will // be modified only at initialization time. // if (fdoData->IdlePrioritySupported == TRUE) { idleRequest = ClasspIsIdleRequest(Pkt->OriginalIrp); if (idleRequest) { InterlockedIncrement(&fdoData->ActiveIdleIoCount); } else { InterlockedIncrement(&fdoData->ActiveIoCount); } } IoSetCompletionRoutine(Pkt->Irp, TransferPktComplete, Pkt, TRUE, TRUE, TRUE); return IoCallDriver(nextDevObj, Pkt->Irp); }
VOID NICFreeRCB( IN PRCB pRCB) /*++ Routine Description: pRCB - pointer to RCB block Arguments: This routine reinitializes the RCB block and puts it back into the RecvFreeList for reuse. Return Value: VOID --*/ { PMP_ADAPTER Adapter = pRCB->Adapter; ULONG ulSendLowW= NIC_SEND_LOW_WATERMARK; DEBUGP(MP_TRACE, ("--> NICFreeRCB %p\n", pRCB)); ASSERT(pRCB->Irp); // shouldn't be NULL ASSERT(!pRCB->Ref); // should be 0 ASSERT(pRCB->Adapter); // shouldn't be NULL IoReuseIrp(pRCB->Irp, STATUS_SUCCESS); pRCB->nextndeoffset=0; pRCB->nextndpoffset=0; pRCB->bIsOver=FALSE; pRCB->ulSize=0; // // Set the MDL field to NULL so that we don't end up double freeing the // MDL in our call to IoFreeIrp. // pRCB->Irp->MdlAddress = NULL; // // Re adjust the length to the originl size // //NdisAdjustBufferLength(pRCB->BufferArray[0], pRCB->ulBufferSize); // // Insert the RCB back in the Recv free list // NdisAcquireSpinLock(&Adapter->RecvLock); RemoveEntryList(&pRCB->List); InsertTailList(&Adapter->RecvFreeList, &pRCB->List); NdisInterlockedDecrement(&Adapter->nBusyRecv); ASSERT(Adapter->nBusyRecv >= 0); NdisReleaseSpinLock(&Adapter->RecvLock); // // For performance, instead of scheduling a workitem at the end of // every read completion, we will do it only when the number of // outstanding IRPs goes below NIC_SEND_LOW_WATERMARK. // We shouldn't queue a workitem if it's already scheduled and waiting in // the system workitem queue to be fired. // if((!ulSendLowW || Adapter->nBusyRecv <= NIC_SEND_LOW_WATERMARK) && MP_TEST_FLAG(Adapter, fMP_POST_READS) && (InterlockedExchange(&Adapter->IsReadWorkItemQueued, TRUE) == FALSE)) { Adapter->nReadWorkItemScheduled++; MP_INC_REF(Adapter); NdisScheduleWorkItem(&Adapter->ReadWorkItem); } DEBUGP(MP_TRACE, ("<-- NICFreeRCB %d\n", Adapter->nBusyRecv)); }
VOID NICFreeNotify( IN PNOTICB pNotiCB) /*++ Routine Description: pRCB - pointer to RCB block Arguments: This routine reinitializes the RCB block and puts it back into the RecvFreeList for reuse. Return Value: VOID --*/ { PMP_ADAPTER Adapter = pNotiCB->Adapter; DEBUGP(MP_TRACE, ("--> NICFreeNotify %p\n", pNotiCB)); ASSERT(pNotiCB->Irp); // shouldn't be NULL ASSERT(!pNotiCB->Ref); // should be 0 ASSERT(pNotiCB->Adapter); // shouldn't be NULL IoReuseIrp(pNotiCB->Irp, STATUS_SUCCESS); pNotiCB->ulSize=0; // // Set the MDL field to NULL so that we don't end up double freeing the // MDL in our call to IoFreeIrp. // pNotiCB->Irp->MdlAddress = NULL; // // Insert the RCB back in the Recv free list // NdisAcquireSpinLock(&Adapter->InterruptNotifyLock); RemoveEntryList(&pNotiCB->List); InsertTailList(&Adapter->InterruptFreeList, &pNotiCB->List); NdisInterlockedDecrement(&Adapter->nBusyNotify); ASSERT(Adapter->nBusyNotify >= 0); NdisReleaseSpinLock(&Adapter->InterruptNotifyLock); // // For performance, instead of scheduling a workitem at the end of // every read completion, we will do it only when the number of // outstanding IRPs goes below NIC_SEND_LOW_WATERMARK. // We shouldn't queue a workitem if it's already scheduled and waiting in // the system workitem queue to be fired. // if((Adapter->nBusyNotify ==0) && MP_TEST_FLAG(Adapter, fMP_POST_INTERRUPT)) { MP_INC_REF(Adapter); NdisScheduleWorkItem(&Adapter->InterruptNotifyItem); } DEBUGP(MP_TRACE, ("<-- NICFreeNotify %d\n", Adapter->nBusyNotify)); }
NTSTATUS IrpCloseFile( IN PDEVICE_OBJECT DeviceObject, IN PFILE_OBJECT FileObject ) { NTSTATUS status; KEVENT event; PIRP irp; PVPB vpb; IO_STATUS_BLOCK ioStatusBlock; PIO_STACK_LOCATION irpSp; PAGED_CODE(); irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); if (irp == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } KeInitializeEvent(&event, SynchronizationEvent, FALSE); irp->Tail.Overlay.OriginalFileObject = FileObject; irp->Tail.Overlay.Thread = PsGetCurrentThread(); irp->RequestorMode = KernelMode; irp->UserEvent = &event; irp->UserIosb = &irp->IoStatus; irp->Overlay.AsynchronousParameters.UserApcRoutine = (PIO_APC_ROUTINE)NULL; irp->Flags = IRP_SYNCHRONOUS_API | IRP_CLOSE_OPERATION; irpSp = IoGetNextIrpStackLocation(irp); irpSp->MajorFunction = IRP_MJ_CLEANUP; irpSp->FileObject = FileObject; status = IoCallDriver(DeviceObject, irp); if (status == STATUS_PENDING) { KeWaitForSingleObject(&event, UserRequest, KernelMode, FALSE, NULL); } IoReuseIrp(irp , STATUS_SUCCESS); KeClearEvent(&event); irpSp = IoGetNextIrpStackLocation(irp); irpSp->MajorFunction = IRP_MJ_CLOSE; irpSp->FileObject = FileObject; irp->UserIosb = &ioStatusBlock; irp->UserEvent = &event; irp->Tail.Overlay.OriginalFileObject = FileObject; irp->Tail.Overlay.Thread = PsGetCurrentThread(); irp->AssociatedIrp.SystemBuffer = (PVOID)NULL; irp->Flags = IRP_CLOSE_OPERATION | IRP_SYNCHRONOUS_API; vpb = FileObject->Vpb; if (vpb && !(FileObject->Flags & FO_DIRECT_DEVICE_OPEN)) { InterlockedDecrement((PLONG)&vpb->ReferenceCount); FileObject->Flags |= FO_FILE_OPEN_CANCELLED; } status = IoCallDriver(DeviceObject, irp); if (status == STATUS_PENDING) { KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, NULL); } //LCXL:ADD- InterlockedIncrement(&FileObject->DeviceObject->ReferenceCount); //ObDereferenceObject(FileObject); //LCXL:Del IoFreeIrp(irp); return status; }