/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
- * FILE: ntoskrnl/io/irp.c
+ * FILE: ntoskrnl/io/iomgr/irp.c
* PURPOSE: IRP Handling Functions
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
* Gunnar Dalsnes
#include <ntoskrnl.h>
#define NDEBUG
-#include <internal/debug.h>
+#include <debug.h>
/* Undefine some macros we implement here */
#undef IoCallDriver
IoFreeIrp(CONTAINING_RECORD(Apc, IRP, Tail.Apc));
}
+NTSTATUS
+NTAPI
+IopCleanupFailedIrp(IN PFILE_OBJECT FileObject,
+ IN PKEVENT EventObject OPTIONAL,
+ IN PVOID Buffer OPTIONAL)
+{
+ PAGED_CODE();
+
+ /* Dereference the event */
+ if (EventObject) ObDereferenceObject(EventObject);
+
+ /* Free a buffer, if any */
+ if (Buffer) ExFreePool(Buffer);
+
+ /* If this was a file opened for synch I/O, then unlock it */
+ if (FileObject->Flags & FO_SYNCHRONOUS_IO) IopUnlockFileObject(FileObject);
+
+ /* Now dereference it and return */
+ ObDereferenceObject(FileObject);
+ return STATUS_INSUFFICIENT_RESOURCES;
+}
+
+VOID
+NTAPI
+IopAbortInterruptedIrp(IN PKEVENT EventObject,
+ IN PIRP Irp)
+{
+ KIRQL OldIrql;
+ BOOLEAN CancelResult;
+ LARGE_INTEGER Wait;
+ PAGED_CODE();
+
+ /* Raise IRQL to APC */
+ KeRaiseIrql(APC_LEVEL, &OldIrql);
+
+ /* Check if nobody completed it yet */
+ if (!KeReadStateEvent(EventObject))
+ {
+ /* First, cancel it */
+ CancelResult = IoCancelIrp(Irp);
+ KeLowerIrql(OldIrql);
+
+ /* Check if we cancelled it */
+ if (CancelResult)
+ {
+ /* Wait for the IRP to be cancelled */
+ Wait.QuadPart = -100000;
+ while (!KeReadStateEvent(EventObject))
+ {
+ /* Delay indefintely */
+ KeDelayExecutionThread(KernelMode, FALSE, &Wait);
+ }
+ }
+ else
+ {
+ /* No cancellation done, so wait for the I/O system to kill it */
+ KeWaitForSingleObject(EventObject,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL);
+ }
+ }
+ else
+ {
+ /* We got preempted, so give up */
+ KeLowerIrql(OldIrql);
+ }
+}
+
VOID
NTAPI
IopRemoveThreadIrp(VOID)
!(Irp->Flags & IRP_SYNCHRONOUS_API) &&
(FileObject))
{
- /* Derefernce the User Event */
+ /* Dereference the User Event */
ObDereferenceObject(Irp->UserEvent);
}
- /* Dereference the File Object */
- if (FileObject) ObDereferenceObject(FileObject);
+ /* Check if we have a file object and this isn't a create operation */
+ if ((FileObject) && !(Irp->Flags & IRP_CREATE_OPERATION))
+ {
+ /* Dereference the file object */
+ ObDereferenceObject(FileObject);
+ }
/* Free the IRP */
IoFreeIrp(Irp);
{
PFILE_OBJECT FileObject;
PIRP Irp;
- PMDL Mdl;
+ PMDL Mdl, NextMdl;
PVOID Port = NULL, Key = NULL;
BOOLEAN SignaledCreateRequest = FALSE;
Irp,
FileObject);
+ /* Sanity check */
+ ASSERT(Irp->IoStatus.Status != (NTSTATUS)0xFFFFFFFF);
+
+ /* Check if we have a file object */
+ if (*SystemArgument2)
+ {
+ /* Check if we're reparsing */
+ if ((Irp->IoStatus.Status == STATUS_REPARSE) &&
+ (Irp->IoStatus.Information == IO_REPARSE_TAG_MOUNT_POINT))
+ {
+ /* We should never get this yet */
+ DPRINT1("Reparse support not yet present!\n");
+ while (TRUE);
+ }
+ }
+
/* Handle Buffered case first */
if (Irp->Flags & IRP_BUFFERED_IO)
{
- /* Check if we have an input buffer and if we suceeded */
- if ((Irp->Flags & IRP_INPUT_OPERATION) &&
+ /* Check if we have an input buffer and if we succeeded */
+ if ((Irp->Flags & IRP_INPUT_OPERATION) &&
(Irp->IoStatus.Status != STATUS_VERIFY_REQUIRED) &&
!(NT_ERROR(Irp->IoStatus.Status)))
{
if (Irp->Flags & IRP_DEALLOCATE_BUFFER)
{
/* Deallocate it */
- ExFreePoolWithTag(Irp->AssociatedIrp.SystemBuffer, TAG_SYS_BUF);
+ ExFreePool(Irp->AssociatedIrp.SystemBuffer);
}
}
Irp->Flags &= ~(IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER);
/* Check if there's an MDL */
- while ((Mdl = Irp->MdlAddress))
+ for (Mdl = Irp->MdlAddress; Mdl; Mdl = NextMdl)
{
- /* Clear all of them */
- Irp->MdlAddress = Mdl->Next;
+ /* Free it */
+ NextMdl = Mdl->Next;
IoFreeMdl(Mdl);
}
+ /* No MDLs left */
+ Irp->MdlAddress = NULL;
+
/*
* Check if either the request was completed without any errors
* (but warnings are OK!), or if it was completed with an error, but
* did return from a pending I/O Operation and is not synchronous.
*/
- if ((!NT_ERROR(Irp->IoStatus.Status)) ||
- (NT_ERROR(Irp->IoStatus.Status) &&
- (Irp->PendingReturned) &&
- !(IsIrpSynchronous(Irp, FileObject))))
+ if (!(NT_ERROR(Irp->IoStatus.Status)) ||
+ (NT_ERROR(Irp->IoStatus.Status) &&
+ (Irp->PendingReturned) &&
+ !(IsIrpSynchronous(Irp, FileObject))))
{
/* Get any information we need from the FO before we kill it */
if ((FileObject) && (FileObject->CompletionContext))
}
/* Use SEH to make sure we don't write somewhere invalid */
- _SEH_TRY
+ _SEH2_TRY
{
/* Save the IOSB Information */
*Irp->UserIosb = Irp->IoStatus;
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Ignore any error */
}
- _SEH_END;
+ _SEH2_END;
/* Check if we have an event or a file object */
if (Irp->UserEvent)
/* Check if we also have a File Object */
if (FileObject)
{
+ /* Check if this is an Asynch API */
+ if (!(Irp->Flags & IRP_SYNCHRONOUS_API))
+ {
+ /* Dereference the event */
+ ObDereferenceObject(Irp->UserEvent);
+ }
+
/*
* Now, if this is a Synch I/O File Object, then this event is
* NOT an actual Executive Event, so we won't dereference it,
* and instead, we will signal the File Object
*/
- if (FileObject->Flags & FO_SYNCHRONOUS_IO)
+ if ((FileObject->Flags & FO_SYNCHRONOUS_IO) &&
+ !(Irp->Flags & IRP_OB_QUERY_NAME))
{
/* Signal the file object and set the status */
KeSetEvent(&FileObject->Event, 0, FALSE);
*/
if (Irp->Flags & IRP_CREATE_OPERATION)
{
- /* Clear the APC Routine and remmeber this */
+ /* Clear the APC Routine and remember this */
Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
SignaledCreateRequest = TRUE;
}
/* Signal the file object and set the status */
KeSetEvent(&FileObject->Event, 0, FALSE);
FileObject->FinalStatus = Irp->IoStatus.Status;
+
+ /*
+ * This could also be a create operation, in which case we want
+ * to make sure there's no APC fired.
+ */
+ if (Irp->Flags & IRP_CREATE_OPERATION)
+ {
+ /* Clear the APC Routine and remember this */
+ Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
+ SignaledCreateRequest = TRUE;
+ }
+ }
+
+ /* Update transfer count for everything but create operation */
+ if (!(Irp->Flags & IRP_CREATE_OPERATION))
+ {
+ if (Irp->Flags & IRP_WRITE_OPERATION)
+ {
+ /* Update write transfer count */
+ IopUpdateTransferCount(IopWriteTransfer,
+ (ULONG)Irp->IoStatus.Information);
+ }
+ else if (Irp->Flags & IRP_READ_OPERATION)
+ {
+ /* Update read transfer count */
+ IopUpdateTransferCount(IopReadTransfer,
+ (ULONG)Irp->IoStatus.Information);
+ }
+ else
+ {
+ /* Update other transfer count */
+ IopUpdateTransferCount(IopOtherTransfer,
+ (ULONG)Irp->IoStatus.Information);
+ }
}
/* Now that we've signaled the events, de-associate the IRP */
- RemoveEntryList(&Irp->ThreadListEntry);
- InitializeListHead(&Irp->ThreadListEntry);
+ IopUnQueueIrpFromThread(Irp);
/* Now check if a User APC Routine was requested */
if (Irp->Overlay.AsynchronousParameters.UserApcRoutine)
{
/* We have an I/O Completion setup... create the special Overlay */
Irp->Tail.CompletionKey = Key;
- Irp->Tail.Overlay.PacketType = IrpCompletionPacket;
+ Irp->Tail.Overlay.PacketType = IopCompletionPacketIrp;
KeInsertQueue(Port, &Irp->Tail.Overlay.ListEntry);
}
else
if ((FileObject) && !(SignaledCreateRequest))
{
/* Dereference it, since it's not needed anymore either */
- ObDereferenceObject(FileObject);
+ ObDereferenceObjectDeferDelete(FileObject);
}
}
else
/* So we did return with a synch operation, was it the IRP? */
if (Irp->Flags & IRP_SYNCHRONOUS_API)
{
- /* Yes, this IRP was synchronous, so retrn the I/O Status */
+ /* Yes, this IRP was synchronous, so return the I/O Status */
*Irp->UserIosb = Irp->IoStatus;
/* Now check if the user gave an event */
if ((FileObject) && !(Irp->Flags & IRP_CREATE_OPERATION))
{
/* Dereference the File Object unless this was a create */
- ObDereferenceObject(FileObject);
+ ObDereferenceObjectDeferDelete(FileObject);
}
/*
}
/* Now that we've signaled the events, de-associate the IRP */
- RemoveEntryList(&Irp->ThreadListEntry);
- InitializeListHead(&Irp->ThreadListEntry);
+ IopUnQueueIrpFromThread(Irp);
/* Free the IRP as well */
IoFreeIrp(Irp);
PNPAGED_LOOKASIDE_LIST List = NULL;
PP_NPAGED_LOOKASIDE_NUMBER ListType = LookasideSmallIrpList;
+ /* Set Charge Quota Flag */
+ if (ChargeQuota) Flags |= IRP_QUOTA_CHARGED;
+
+ /* FIXME: Implement Lookaside Floats */
+
/* Figure out which Lookaside List to use */
if ((StackSize <= 8) && (ChargeQuota == FALSE))
{
/* Did we try lookaside and fail? */
if (Flags & IRP_ALLOCATED_FIXED_SIZE) List->L.AllocateMisses++;
- /* Check if we shoudl charge quota */
+ /* Check if we should charge quota */
if (ChargeQuota)
{
/* Irp = ExAllocatePoolWithQuotaTag(NonPagedPool, Size, TAG_IRP); */
}
else
{
- /* We have an IRP from Lookaside */
- Flags |= IRP_LOOKASIDE_ALLOCATION;
+ /* In this case there is no charge quota */
+ Flags &= ~IRP_QUOTA_CHARGED;
}
- /* Set Flag */
- if (ChargeQuota) Flags |= IRP_QUOTA_CHARGED;
-
/* Now Initialize it */
IoInitializeIrp(Irp, Size, StackSize);
/* Allocate IRP */
Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
- if (!Irp) return Irp;
+ if (!Irp) return NULL;
/* Get the Stack */
StackPtr = IoGetNextIrpStackLocation(Irp);
return NULL;
}
- /* Probe and Lock */
- _SEH_TRY
- {
- /* Do the probe */
- MmProbeAndLockPages(Irp->MdlAddress,
- KernelMode,
- MajorFunction == IRP_MJ_READ ?
- IoWriteAccess : IoReadAccess);
- }
- _SEH_HANDLE
- {
- /* Free the IRP and its MDL */
- IoFreeMdl(Irp->MdlAddress);
- IoFreeIrp(Irp);
- Irp = NULL;
- }
- _SEH_END;
-
- /* This is how we know if we failed during the probe */
- if (!Irp) return NULL;
+ /* Probe and Lock */
+ _SEH2_TRY
+ {
+ /* Do the probe */
+ MmProbeAndLockPages(Irp->MdlAddress,
+ KernelMode,
+ MajorFunction == IRP_MJ_READ ?
+ IoWriteAccess : IoReadAccess);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Free the IRP and its MDL */
+ IoFreeMdl(Irp->MdlAddress);
+ IoFreeIrp(Irp);
+
+ /* Fail */
+ _SEH2_YIELD(return NULL);
+ }
+ _SEH2_END;
}
else
{
Irp->UserIosb = IoStatusBlock;
Irp->Tail.Overlay.Thread = PsGetCurrentThread();
- /* Set the Status Block after all is done */
+ /* Return the IRP */
IOTRACE(IO_IRP_DEBUG,
"%s - Built IRP %p with Major, Buffer, DO %lx %p %p\n",
__FUNCTION__,
/* Allocate IRP */
Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
- if (!Irp) return Irp;
+ if (!Irp) return NULL;
/* Get the Stack */
StackPtr = IoGetNextIrpStackLocation(Irp);
}
else
{
+ /* Clear the flags */
Irp->Flags = 0;
}
}
/* Probe and Lock */
- _SEH_TRY
+ _SEH2_TRY
{
/* Do the probe */
MmProbeAndLockPages(Irp->MdlAddress,
METHOD_IN_DIRECT ?
IoReadAccess : IoWriteAccess);
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Free the MDL */
IoFreeMdl(Irp->MdlAddress);
/* Free the input buffer and IRP */
if (InputBuffer) ExFreePool(Irp->AssociatedIrp.SystemBuffer);
IoFreeIrp(Irp);
- Irp = NULL;
- }
- _SEH_END;
- /* This is how we know if probing failed */
- if (!Irp) return NULL;
+ /* Fail */
+ _SEH2_YIELD(return NULL);
+ }
+ _SEH2_END;
}
break;
IoCancelIrp(IN PIRP Irp)
{
KIRQL OldIrql;
+ KIRQL IrqlAtEntry;
PDRIVER_CANCEL CancelRoutine;
IOTRACE(IO_IRP_DEBUG,
"%s - Canceling IRP %p\n",
__FUNCTION__,
Irp);
ASSERT(Irp->Type == IO_TYPE_IRP);
+ IrqlAtEntry = KeGetCurrentIrql();
/* Acquire the cancel lock and cancel the IRP */
IoAcquireCancelSpinLock(&OldIrql);
Irp->Cancel = TRUE;
/* Clear the cancel routine and get the old one */
- CancelRoutine = IoSetCancelRoutine(Irp, NULL);
+ CancelRoutine = (PVOID)IoSetCancelRoutine(Irp, NULL);
if (CancelRoutine)
{
/* We had a routine, make sure the IRP isn't completed */
/* Set the cancel IRQL And call the routine */
Irp->CancelIrql = OldIrql;
CancelRoutine(IoGetCurrentIrpStackLocation(Irp)->DeviceObject, Irp);
+ ASSERT(IrqlAtEntry == KeGetCurrentIrql());
return TRUE;
}
Thread);
/* Raise to APC to protect the IrpList */
- OldIrql = KfRaiseIrql(APC_LEVEL);
+ KeRaiseIrql(APC_LEVEL, &OldIrql);
/* Start by cancelling all the IRPs in the current thread queue. */
ListHead = &Thread->IrpList;
while (!IsListEmpty(&Thread->IrpList))
{
/* Now we can lower */
- KfLowerIrql(OldIrql);
+ KeLowerIrql(OldIrql);
/* Wait a short while and then look if all our IRPs were completed. */
KeDelayExecutionThread(KernelMode, FALSE, &Interval);
* Don't stay here forever if some broken driver doesn't complete
* the IRP.
*/
- if (!(Retries--)) IopRemoveThreadIrp();
+ if (!(Retries--))
+ {
+ /* Print out a message and remove the IRP */
+ DPRINT1("Broken driver did not complete!\n");
+ IopRemoveThreadIrp();
+ }
/* Raise the IRQL Again */
- OldIrql = KfRaiseIrql(APC_LEVEL);
+ KeRaiseIrql(APC_LEVEL, &OldIrql);
}
/* We're done, lower the IRQL */
- KfLowerIrql(OldIrql);
+ KeLowerIrql(OldIrql);
}
/*
IoCallDriver(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
- /* Call fast call */
+ /* Call fastcall */
return IofCallDriver(DeviceObject, Irp);
}
IN PIRP Irp)
{
PDRIVER_OBJECT DriverObject;
- PIO_STACK_LOCATION Param;
+ PIO_STACK_LOCATION StackPtr;
+
+ /* Make sure this is a valid IRP */
+ ASSERT(Irp->Type == IO_TYPE_IRP);
/* Get the Driver Object */
DriverObject = DeviceObject->DriverObject;
}
/* Now update the stack location */
- Param = IoGetNextIrpStackLocation(Irp);
- Irp->Tail.Overlay.CurrentStackLocation = Param;
+ StackPtr = IoGetNextIrpStackLocation(Irp);
+ Irp->Tail.Overlay.CurrentStackLocation = StackPtr;
/* Get the Device Object */
- Param->DeviceObject = DeviceObject;
+ StackPtr->DeviceObject = DeviceObject;
/* Call it */
- return DriverObject->MajorFunction[Param->MajorFunction](DeviceObject,
- Irp);
+ return DriverObject->MajorFunction[StackPtr->MajorFunction](DeviceObject,
+ Irp);
+}
+
+FORCEINLINE
+VOID
+IopClearStackLocation(IN PIO_STACK_LOCATION IoStackLocation)
+{
+ IoStackLocation->MinorFunction = 0;
+ IoStackLocation->Flags = 0;
+ IoStackLocation->Control &= SL_ERROR_RETURNED;
+ IoStackLocation->Parameters.Others.Argument1 = 0;
+ IoStackLocation->Parameters.Others.Argument2 = 0;
+ IoStackLocation->Parameters.Others.Argument3 = 0;
+ IoStackLocation->FileObject = NULL;
}
/*
IofCompleteRequest(IN PIRP Irp,
IN CCHAR PriorityBoost)
{
- PIO_STACK_LOCATION StackPtr;
+ PIO_STACK_LOCATION StackPtr, LastStackPtr;
PDEVICE_OBJECT DeviceObject;
PFILE_OBJECT FileObject;
PETHREAD Thread;
NTSTATUS Status;
- PMDL Mdl;
- ULONG MasterIrpCount;
+ 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 more then once */
+ /* Make sure this IRP isn't getting completed twice or is invalid */
if ((Irp->CurrentLocation) > (Irp->StackCount + 1))
{
/* Bugcheck */
}
/* Some sanity checks */
- ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
+ 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 = PtrToUlong(LastStackPtr->Parameters.Others.Argument4);
+ }
/* Get the Current Stack and skip it */
StackPtr = IoGetCurrentIrpStackLocation(Irp);
/* 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 = UlongToPtr(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)))
+ (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))
{
/* Mark it as pending */
IoMarkIrpPending(Irp);
}
+
+ /* Clear the stack location */
+ IopClearStackLocation(StackPtr);
}
/* Move to next stack location and pointer */
/* Check if the IRP is an associated IRP */
if (Irp->Flags & IRP_ASSOCIATED_IRP)
{
- /* This should never happen! */
- ASSERT(IsListEmpty(&Irp->ThreadListEntry));
-
/* Get the master IRP and count */
MasterIrp = Irp->AssociatedIrp.MasterIrp;
- MasterIrpCount = InterlockedDecrement(&MasterIrp->
- AssociatedIrp.IrpCount);
-
- /* Set the thread of this IRP as the master's */
- Irp->Tail.Overlay.Thread = MasterIrp->Tail.Overlay.Thread;
+ MasterCount = InterlockedDecrement(&MasterIrp->AssociatedIrp.IrpCount);
/* Free the MDLs */
- while ((Mdl = Irp->MdlAddress))
+ for (Mdl = Irp->MdlAddress; Mdl; Mdl = NextMdl)
{
/* Go to the next one */
- Irp->MdlAddress = Mdl->Next;
+ NextMdl = Mdl->Next;
IoFreeMdl(Mdl);
}
IoFreeIrp(Irp);
/* Complete the Master IRP */
- if (!MasterIrpCount) IofCompleteRequest(MasterIrp, PriorityBoost);
+ 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)
{
/* Check if this is a Paging I/O or Close Operation */
if (Irp->Flags & (IRP_PAGING_IO | IRP_CLOSE_OPERATION))
{
- /* This should never happen! */
- ASSERT(IsListEmpty(&Irp->ThreadListEntry));
-
- /* Handle a Close Operation or Sync Paging I/O (see page 165) */
+ /* 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 (Irp->Flags & IRP_SYNCHRONOUS_PAGING_IO) IoFreeIrp(Irp);
+ if (Flags) IoFreeIrp(Irp);
}
else
{
PriorityBoost);
#else
/* Not implemented yet. */
- ASSERT(FALSE);
+ DPRINT1("Not supported!\n");
+ while (TRUE);
#endif
}
Mdl = Irp->MdlAddress;
while (Mdl)
{
- MmUnlockPages(Mdl);
+ MmUnlockPages(Mdl);
Mdl = Mdl->Next;
}
Thread = Irp->Tail.Overlay.Thread;
FileObject = Irp->Tail.Overlay.OriginalFileObject;
- /* Make sure the IRP isn't cancelled */
+ /* Make sure the IRP isn't canceled */
if (!Irp->Cancel)
{
/* Initialize the APC */
}
else
{
- /* The IRP just got cancelled... does a thread still own it? */
+ /* The IRP just got canceled... does a thread still own it? */
Thread = Irp->Tail.Overlay.Thread;
if (Thread)
{
else
{
/* Nothing left for us to do, kill it */
+ ASSERT(Irp->Cancel);
IopCleanupIrp(Irp, FileObject);
}
}
}
+NTSTATUS
+NTAPI
+IopSynchronousCompletion(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID Context)
+{
+ if (Irp->PendingReturned)
+ KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE);
+ return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
/*
- * @unimplemented
+ * @implemented
*/
BOOLEAN
NTAPI
IoForwardIrpSynchronously(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
- UNIMPLEMENTED;
- return FALSE;
+ KEVENT Event;
+ NTSTATUS Status;
+
+ /* Check if next stack location is available */
+ if (Irp->CurrentLocation < Irp->StackCount)
+ {
+ /* No more stack location */
+ return FALSE;
+ }
+
+ /* Initialize event */
+ KeInitializeEvent(&Event, NotificationEvent, FALSE);
+
+ /* Copy stack location for next driver */
+ IoCopyCurrentIrpStackLocationToNext(Irp);
+
+ /* Set a completion routine, which will signal the event */
+ IoSetCompletionRoutine(Irp, IopSynchronousCompletion, &Event, TRUE, TRUE, TRUE);
+
+ /* Call next driver */
+ Status = IoCallDriver(DeviceObject, Irp);
+
+ /* Check if irp is pending */
+ if (Status == STATUS_PENDING)
+ {
+ /* Yes, wait for its completion */
+ KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
+ }
+
+ /* Return success */
+ return TRUE;
}
/*
Irp);
/* Make sure the Thread IRP list is empty and that it OK to free it */
+ ASSERT(Irp->Type == IO_TYPE_IRP);
ASSERT(IsListEmpty(&Irp->ThreadListEntry));
ASSERT(Irp->CurrentLocation >= Irp->StackCount);
if (!(Irp->AllocationFlags & IRP_ALLOCATED_FIXED_SIZE))
{
/* Free it */
- ExFreePool(Irp);
+ ExFreePoolWithTag(Irp, TAG_IRP);
}
else
{
{
/* All lists failed, use the pool */
List->L.FreeMisses++;
- ExFreePool(Irp);
+ ExFreePoolWithTag(Irp, TAG_IRP);
Irp = NULL;
}
}
/*
* @implemented
*/
-PEPROCESS NTAPI
+IO_PAGING_PRIORITY
+FASTCALL
+IoGetPagingIoPriority(IN PIRP Irp)
+{
+ IO_PAGING_PRIORITY Priority;
+ ULONG Flags;
+
+ /* Get the flags */
+ Flags = Irp->Flags;
+
+ /* Check what priority it has */
+ if (Flags & 0x8000) // FIXME: Undocumented flag
+ {
+ /* High priority */
+ Priority = IoPagingPriorityHigh;
+ }
+ else if (Flags & IRP_PAGING_IO)
+ {
+ /* Normal priority */
+ Priority = IoPagingPriorityNormal;
+ }
+ else
+ {
+ /* Invalid -- not a paging IRP */
+ Priority = IoPagingPriorityInvalid;
+ }
+
+ /* Return the priority */
+ return Priority;
+}
+
+/*
+ * @implemented
+ */
+PEPROCESS
+NTAPI
IoGetRequestorProcess(IN PIRP Irp)
{
- return(Irp->Tail.Overlay.Thread->ThreadsProcess);
+ /* Return the requestor process */
+ return Irp->Tail.Overlay.Thread->ThreadsProcess;
}
/*
NTAPI
IoGetRequestorProcessId(IN PIRP Irp)
{
- return (ULONG)(IoGetRequestorProcess(Irp)->UniqueProcessId);
+ /* Return the requestor process' id */
+ return PtrToUlong(IoGetRequestorProcess(Irp)->UniqueProcessId);
}
/*
NTAPI
IoGetTopLevelIrp(VOID)
{
+ /* Return the IRP */
return (PIRP)PsGetCurrentThread()->TopLevelIrp;
}
IoIsOperationSynchronous(IN PIRP Irp)
{
/* Check the flags */
- if (((Irp->Flags & IRP_SYNCHRONOUS_PAGING_IO) &&
- (!(Irp->Flags & IRP_PAGING_IO) &&
- !(Irp->Flags & IRP_SYNCHRONOUS_PAGING_IO))) ||
- (Irp->Flags & IRP_SYNCHRONOUS_API) ||
- (IoGetCurrentIrpStackLocation(Irp)->FileObject->Flags &
- FO_SYNCHRONOUS_IO))
+ if (!(Irp->Flags & (IRP_PAGING_IO | IRP_SYNCHRONOUS_PAGING_IO)) &&
+ ((Irp->Flags & IRP_SYNCHRONOUS_PAGING_IO) ||
+ (Irp->Flags & IRP_SYNCHRONOUS_API) ||
+ (IoGetCurrentIrpStackLocation(Irp)->FileObject->Flags &
+ FO_SYNCHRONOUS_IO)))
{
/* Synch API or Paging I/O is OK, as is Sync File I/O */
return TRUE;
IoSetTopLevelIrp(IN PIRP Irp)
{
/* Set the IRP */
- PsGetCurrentThread()->TopLevelIrp = (ULONG)Irp;
+ PsGetCurrentThread()->TopLevelIrp = (ULONG_PTR)Irp;
}
-
-/* EOF */