IoCompleteRequest in ReactOS
VOID NTAPI IoCompleteRequest(IN PIRP Irp, IN CCHAR PriorityBoost) { /* Call the fastcall */ IofCompleteRequest(Irp, PriorityBoost); } VOID FASTCALL IofCompleteRequest(IN PIRP Irp, IN CCHAR PriorityBoost) { PIO_STACK_LOCATION StackPtr, LastStackPtr; PDEVICE_OBJECT DeviceObject; PFILE_OBJECT FileObject; PETHREAD Thread; NTSTATUS Status; PMDL Mdl, NextMdl; ULONG MasterCount; PIRP MasterIrp; ULONG Flags; NTSTATUS ErrorCode = STATUS_SUCCESS; IOTRACE(IO_IRP_DEBUG, "%s - Completing IRP %p\n", __FUNCTION__, Irp); /* Make sure this IRP isn't getting completed twice or is invalid */ if ((Irp->CurrentLocation) > (Irp->StackCount + 1)) { /* Bugcheck */ KeBugCheckEx(MULTIPLE_IRP_COMPLETE_REQUESTS, (ULONG_PTR)Irp, 0, 0, 0); } /* Some sanity checks */ ASSERT(Irp->Type == IO_TYPE_IRP); ASSERT(!Irp->CancelRoutine); ASSERT(Irp->IoStatus.Status != STATUS_PENDING); ASSERT(Irp->IoStatus.Status != (NTSTATUS)0xFFFFFFFF); /* Get the last stack */ LastStackPtr = (PIO_STACK_LOCATION)(Irp + 1); if (LastStackPtr->Control & SL_ERROR_RETURNED) { /* Get the error code */ ErrorCode = (NTSTATUS)LastStackPtr->Parameters.Others.Argument4; } /* Get the Current Stack and skip it */ StackPtr = IoGetCurrentIrpStackLocation(Irp); IoSkipCurrentIrpStackLocation(Irp); /* Loop the Stacks and complete the IRPs */ do { /* Set Pending Returned */ Irp->PendingReturned = StackPtr->Control & SL_PENDING_RETURNED; /* Check if we failed */ if (!NT_SUCCESS(Irp->IoStatus.Status)) { /* Check if it was changed by a completion routine */ if (Irp->IoStatus.Status != ErrorCode) { /* Update the error for the current stack */ ErrorCode = Irp->IoStatus.Status; StackPtr->Control |= SL_ERROR_RETURNED; LastStackPtr->Parameters.Others.Argument4 = (PVOID)ErrorCode; LastStackPtr->Control |= SL_ERROR_RETURNED; } } /* Check if there is a Completion Routine to Call */ if ((NT_SUCCESS(Irp->IoStatus.Status) && (StackPtr->Control & SL_INVOKE_ON_SUCCESS)) || (!NT_SUCCESS(Irp->IoStatus.Status) && (StackPtr->Control & SL_INVOKE_ON_ERROR)) || (Irp->Cancel && (StackPtr->Control & SL_INVOKE_ON_CANCEL))) { /* Clear the stack location */ IopClearStackLocation(StackPtr); /* Check for highest-level device completion routines */ if (Irp->CurrentLocation == (Irp->StackCount + 1)) { /* Clear the DO, since the current stack location is invalid */ DeviceObject = NULL; } else { /* Otherwise, return the real one */ DeviceObject = IoGetCurrentIrpStackLocation(Irp)->DeviceObject; } /* Call the completion routine */ Status = StackPtr->CompletionRoutine(DeviceObject, Irp, StackPtr->Context); /* Don't touch the Packet in this case, since it might be gone! */ if (Status == STATUS_MORE_PROCESSING_REQUIRED) return; } else { /* Otherwise, check if this is a completed IRP */ if ((Irp->CurrentLocation <= Irp->StackCount) && (Irp->PendingReturned)) { /* Mark it as pending */ IoMarkIrpPending(Irp); } /* Clear the stack location */ IopClearStackLocation(StackPtr); } /* Move to next stack location and pointer */ IoSkipCurrentIrpStackLocation(Irp); StackPtr++; } while (Irp->CurrentLocation <= (Irp->StackCount + 1)); /* Check if the IRP is an associated IRP */ if (Irp->Flags & IRP_ASSOCIATED_IRP) { /* Get the master IRP and count */ MasterIrp = Irp->AssociatedIrp.MasterIrp; MasterCount = InterlockedDecrement(&MasterIrp->AssociatedIrp.IrpCount); /* Free the MDLs */ for (Mdl = Irp->MdlAddress; Mdl; Mdl = NextMdl) { /* Go to the next one */ NextMdl = Mdl->Next; IoFreeMdl(Mdl); } /* Free the IRP itself */ IoFreeIrp(Irp); /* Complete the Master IRP */ if (!MasterCount) IofCompleteRequest(MasterIrp, PriorityBoost); return; } /* We don't support this yet */ ASSERT(Irp->IoStatus.Status != STATUS_REPARSE); /* Check if we have an auxiliary buffer */ if (Irp->Tail.Overlay.AuxiliaryBuffer) { /* Free it */ ExFreePool(Irp->Tail.Overlay.AuxiliaryBuffer); Irp->Tail.Overlay.AuxiliaryBuffer = NULL; } /* Check if this is a Paging I/O or Close Operation */ if (Irp->Flags & (IRP_PAGING_IO | IRP_CLOSE_OPERATION)) { /* Handle a Close Operation or Sync Paging I/O */ if (Irp->Flags & (IRP_SYNCHRONOUS_PAGING_IO | IRP_CLOSE_OPERATION)) { /* Set the I/O Status and Signal the Event */ Flags = Irp->Flags & (IRP_SYNCHRONOUS_PAGING_IO | IRP_PAGING_IO); *Irp->UserIosb = Irp->IoStatus; KeSetEvent(Irp->UserEvent, PriorityBoost, FALSE); /* Free the IRP for a Paging I/O Only, Close is handled by us */ if (Flags) IoFreeIrp(Irp); } else { #if 0 /* Page 166 */ KeInitializeApc(&Irp->Tail.Apc &Irp->Tail.Overlay.Thread->Tcb, Irp->ApcEnvironment, IopCompletePageWrite, NULL, NULL, KernelMode, NULL); KeInsertQueueApc(&Irp->Tail.Apc, NULL, NULL, PriorityBoost); #else /* Not implemented yet. */ DPRINT1("Not supported!\n"); while (TRUE); #endif } /* Get out of here */ return; } /* Unlock MDL Pages, page 167. */ Mdl = Irp->MdlAddress; while (Mdl) { MmUnlockPages(Mdl); Mdl = Mdl->Next; } /* Check if we should exit because of a Deferred I/O (page 168) */ if ((Irp->Flags & IRP_DEFER_IO_COMPLETION) && !(Irp->PendingReturned)) { /* * Return without queuing the completion APC, since the caller will * take care of doing its own optimized completion at PASSIVE_LEVEL. */ return; } /* Get the thread and file object */ Thread = Irp->Tail.Overlay.Thread; FileObject = Irp->Tail.Overlay.OriginalFileObject; /* Make sure the IRP isn't canceled */ if (!Irp->Cancel) { /* Initialize the APC */ KeInitializeApc(&Irp->Tail.Apc, &Thread->Tcb, Irp->ApcEnvironment, IopCompleteRequest, NULL, NULL, KernelMode, NULL); /* Queue it */ KeInsertQueueApc(&Irp->Tail.Apc, FileObject, NULL, /* This is used for REPARSE stuff */ PriorityBoost); } else { /* The IRP just got canceled... does a thread still own it? */ Thread = Irp->Tail.Overlay.Thread; if (Thread) { /* Yes! There is still hope! Initialize the APC */ KeInitializeApc(&Irp->Tail.Apc, &Thread->Tcb, Irp->ApcEnvironment, IopCompleteRequest, NULL, NULL, KernelMode, NULL); /* Queue it */ KeInsertQueueApc(&Irp->Tail.Apc, FileObject, NULL, /* This is used for REPARSE stuff */ PriorityBoost); } else { /* Nothing left for us to do, kill it */ ASSERT(Irp->Cancel); IopCleanupIrp(Irp, FileObject); } } }
'Windows Programming > 드라이버' 카테고리의 다른 글
Driver Basic (0) | 2011.04.20 |
---|---|
[드라이버] 프로세스 풀패스구하기 (0) | 2009.07.01 |
signtool.exe (0) | 2009.05.27 |
IoCallDriver in ReactOS (0) | 2009.05.18 |
FsRtlRegisterFileSystemFilterCallbacks() - FileMap을 이용한 파일엑세스 모니터링 (1) | 2009.05.15 |