Author: ion
Date: Sun Jul 2 22:20:37 2006
New Revision: 22772
URL:
http://svn.reactos.org/svn/reactos?rev=22772&view=rev
Log:
- Move NtCancelIoFile and NtDeleteFile to file.c, they don't deal with IRPs.
- Create IopFinalizeAsynchronousIo to deal with Sync APIs working on Async file objects,
which need to be waited on differently and have the IOSB copied manually.
- Update NtFlushBuffersFile to new semantics (ie, usage of the new implemented
functions).
Modified:
trunk/reactos/ntoskrnl/io/iomgr/file.c
trunk/reactos/ntoskrnl/io/iomgr/iofunc.c
Modified: trunk/reactos/ntoskrnl/io/iomgr/file.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/file.c?r…
==============================================================================
--- trunk/reactos/ntoskrnl/io/iomgr/file.c (original)
+++ trunk/reactos/ntoskrnl/io/iomgr/file.c Sun Jul 2 22:20:37 2006
@@ -1469,6 +1469,141 @@
FileInformation);
}
+/**
+ * @name NtCancelIoFile
+ *
+ * Cancel all pending I/O operations in the current thread for specified
+ * file object.
+ *
+ * @param FileHandle
+ * Handle to file object to cancel requests for. No specific
+ * access rights are needed.
+ * @param IoStatusBlock
+ * Pointer to status block which is filled with final completition
+ * status on successful return.
+ *
+ * @return Status.
+ *
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+NtCancelIoFile(IN HANDLE FileHandle,
+ OUT PIO_STATUS_BLOCK IoStatusBlock)
+{
+ PFILE_OBJECT FileObject;
+ PETHREAD Thread;
+ PIRP Irp;
+ KIRQL OldIrql;
+ BOOLEAN OurIrpsInList = FALSE;
+ LARGE_INTEGER Interval;
+ KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
+ NTSTATUS Status = STATUS_SUCCESS;
+ PAGED_CODE();
+
+ if (PreviousMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ ProbeForWrite(IoStatusBlock,
+ sizeof(IO_STATUS_BLOCK),
+ sizeof(ULONG));
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if (!NT_SUCCESS(Status)) return Status;
+ }
+
+ Status = ObReferenceObjectByHandle(FileHandle,
+ 0,
+ IoFileObjectType,
+ PreviousMode,
+ (PVOID*)&FileObject,
+ NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* IRP cancellations are synchronized at APC_LEVEL. */
+ OldIrql = KfRaiseIrql(APC_LEVEL);
+
+ /*
+ * Walk the list of active IRPs and cancel the ones that belong to
+ * our file object.
+ */
+
+ Thread = PsGetCurrentThread();
+
+ LIST_FOR_EACH(Irp, &Thread->IrpList, IRP, ThreadListEntry)
+ {
+ if (Irp->Tail.Overlay.OriginalFileObject == FileObject)
+ {
+ IoCancelIrp(Irp);
+ /* Don't break here, we want to cancel all IRPs for the file object. */
+ OurIrpsInList = TRUE;
+ }
+ }
+
+ KfLowerIrql(OldIrql);
+
+ while (OurIrpsInList)
+ {
+ OurIrpsInList = FALSE;
+
+ /* Wait a short while and then look if all our IRPs were completed. */
+ Interval.QuadPart = -1000000; /* 100 milliseconds */
+ KeDelayExecutionThread(KernelMode, FALSE, &Interval);
+
+ OldIrql = KfRaiseIrql(APC_LEVEL);
+
+ /*
+ * Look in the list if all IRPs for the specified file object
+ * are completed (or cancelled). If someone sends a new IRP
+ * for our file object while we're here we can happily loop
+ * forever.
+ */
+
+ LIST_FOR_EACH(Irp, &Thread->IrpList, IRP, ThreadListEntry)
+ {
+ if (Irp->Tail.Overlay.OriginalFileObject == FileObject)
+ {
+ OurIrpsInList = TRUE;
+ break;
+ }
+ }
+
+ KfLowerIrql(OldIrql);
+ }
+
+ _SEH_TRY
+ {
+ IoStatusBlock->Status = STATUS_SUCCESS;
+ IoStatusBlock->Information = 0;
+ Status = STATUS_SUCCESS;
+ }
+ _SEH_HANDLE
+ {
+
+ }
+ _SEH_END;
+
+ ObDereferenceObject(FileObject);
+ return Status;
+}
+
+/*
+ * @unimplemented
+ */
+NTSTATUS
+NTAPI
+NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes)
+{
+ UNIMPLEMENTED;
+ return(STATUS_NOT_IMPLEMENTED);
+}
+
/*
* @unimplemented
*/
Modified: trunk/reactos/ntoskrnl/io/iomgr/iofunc.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/iofunc.c…
==============================================================================
--- trunk/reactos/ntoskrnl/io/iomgr/iofunc.c (original)
+++ trunk/reactos/ntoskrnl/io/iomgr/iofunc.c Sun Jul 2 22:20:37 2006
@@ -89,6 +89,54 @@
/* We got preempted, so give up */
KeLowerIrql(OldIrql);
}
+}
+
+NTSTATUS
+NTAPI
+IopFinalizeAsynchronousIo(IN NTSTATUS SynchStatus,
+ IN PKEVENT Event,
+ IN PIRP Irp,
+ IN KPROCESSOR_MODE PreviousMode,
+ IN PIO_STATUS_BLOCK KernelIosb,
+ OUT PIO_STATUS_BLOCK IoStatusBlock)
+{
+ NTSTATUS FinalStatus = SynchStatus;
+ PAGED_CODE();
+
+ /* Make sure the IRP was completed, but returned pending */
+ if (FinalStatus == STATUS_PENDING)
+ {
+ /* Wait for the IRP */
+ FinalStatus = KeWaitForSingleObject(Event,
+ Executive,
+ PreviousMode,
+ FALSE,
+ NULL);
+ if (FinalStatus == STATUS_USER_APC)
+ {
+ /* Abort the request */
+ IopAbortInterruptedIrp(Event, Irp);
+ }
+
+ /* Set the final status */
+ FinalStatus = KernelIosb->Status;
+ }
+
+ /* Wrap potential user-mode write in SEH */
+ _SEH_TRY
+ {
+ *IoStatusBlock = *KernelIosb;
+ }
+ _SEH_HANDLE
+ {
+ /* Get the exception code */
+ FinalStatus = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ /* Free the event and return status */
+ ExFreePool(Event);
+ return FinalStatus;
}
NTSTATUS
@@ -734,141 +782,6 @@
/* NATIVE SERVICES ***********************************************************/
-/**
- * @name NtCancelIoFile
- *
- * Cancel all pending I/O operations in the current thread for specified
- * file object.
- *
- * @param FileHandle
- * Handle to file object to cancel requests for. No specific
- * access rights are needed.
- * @param IoStatusBlock
- * Pointer to status block which is filled with final completition
- * status on successful return.
- *
- * @return Status.
- *
- * @implemented
- */
-NTSTATUS
-NTAPI
-NtCancelIoFile(IN HANDLE FileHandle,
- OUT PIO_STATUS_BLOCK IoStatusBlock)
-{
- PFILE_OBJECT FileObject;
- PETHREAD Thread;
- PIRP Irp;
- KIRQL OldIrql;
- BOOLEAN OurIrpsInList = FALSE;
- LARGE_INTEGER Interval;
- KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
- NTSTATUS Status = STATUS_SUCCESS;
- PAGED_CODE();
-
- if (PreviousMode != KernelMode)
- {
- _SEH_TRY
- {
- ProbeForWrite(IoStatusBlock,
- sizeof(IO_STATUS_BLOCK),
- sizeof(ULONG));
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
-
- if (!NT_SUCCESS(Status)) return Status;
- }
-
- Status = ObReferenceObjectByHandle(FileHandle,
- 0,
- IoFileObjectType,
- PreviousMode,
- (PVOID*)&FileObject,
- NULL);
- if (!NT_SUCCESS(Status)) return Status;
-
- /* IRP cancellations are synchronized at APC_LEVEL. */
- OldIrql = KfRaiseIrql(APC_LEVEL);
-
- /*
- * Walk the list of active IRPs and cancel the ones that belong to
- * our file object.
- */
-
- Thread = PsGetCurrentThread();
-
- LIST_FOR_EACH(Irp, &Thread->IrpList, IRP, ThreadListEntry)
- {
- if (Irp->Tail.Overlay.OriginalFileObject == FileObject)
- {
- IoCancelIrp(Irp);
- /* Don't break here, we want to cancel all IRPs for the file object. */
- OurIrpsInList = TRUE;
- }
- }
-
- KfLowerIrql(OldIrql);
-
- while (OurIrpsInList)
- {
- OurIrpsInList = FALSE;
-
- /* Wait a short while and then look if all our IRPs were completed. */
- Interval.QuadPart = -1000000; /* 100 milliseconds */
- KeDelayExecutionThread(KernelMode, FALSE, &Interval);
-
- OldIrql = KfRaiseIrql(APC_LEVEL);
-
- /*
- * Look in the list if all IRPs for the specified file object
- * are completed (or cancelled). If someone sends a new IRP
- * for our file object while we're here we can happily loop
- * forever.
- */
-
- LIST_FOR_EACH(Irp, &Thread->IrpList, IRP, ThreadListEntry)
- {
- if (Irp->Tail.Overlay.OriginalFileObject == FileObject)
- {
- OurIrpsInList = TRUE;
- break;
- }
- }
-
- KfLowerIrql(OldIrql);
- }
-
- _SEH_TRY
- {
- IoStatusBlock->Status = STATUS_SUCCESS;
- IoStatusBlock->Information = 0;
- Status = STATUS_SUCCESS;
- }
- _SEH_HANDLE
- {
-
- }
- _SEH_END;
-
- ObDereferenceObject(FileObject);
- return Status;
-}
-
-/*
- * @unimplemented
- */
-NTSTATUS
-NTAPI
-NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes)
-{
- UNIMPLEMENTED;
- return(STATUS_NOT_IMPLEMENTED);
-}
-
/*
* @implemented
*/
@@ -933,32 +846,36 @@
NtFlushBuffersFile(IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock)
{
- PFILE_OBJECT FileObject = NULL;
+ PFILE_OBJECT FileObject;
PIRP Irp;
PIO_STACK_LOCATION StackPtr;
NTSTATUS Status = STATUS_SUCCESS;
PDEVICE_OBJECT DeviceObject;
- KEVENT Event;
+ PKEVENT Event = NULL;
BOOLEAN LocalEvent = FALSE;
- ACCESS_MASK DesiredAccess = FILE_WRITE_DATA;
OBJECT_HANDLE_INFORMATION ObjectHandleInfo;
KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
+ IO_STATUS_BLOCK KernelIosb;
PAGED_CODE();
if (PreviousMode != KernelMode)
{
+ /* Protect probes */
_SEH_TRY
{
+ /* Probe the I/O Status block */
ProbeForWrite(IoStatusBlock,
sizeof(IO_STATUS_BLOCK),
sizeof(ULONG));
}
_SEH_HANDLE
{
+ /* Get the exception code */
Status = _SEH_GetExceptionCode();
}
_SEH_END;
+ /* Return exception code, if any */
if (!NT_SUCCESS(Status)) return Status;
}
@@ -969,58 +886,55 @@
PreviousMode,
(PVOID*)&FileObject,
&ObjectHandleInfo);
- if (!NT_SUCCESS(Status)) return(Status);
-
- /* check if the handle has either FILE_WRITE_DATA or FILE_APPEND_DATA was
- granted. However, if this is a named pipe, make sure we don't ask for
- FILE_APPEND_DATA as it interferes with the FILE_CREATE_PIPE_INSTANCE
- access right! */
- if (!(FileObject->Flags & FO_NAMED_PIPE))
- DesiredAccess |= FILE_APPEND_DATA;
- if (!RtlAreAnyAccessesGranted(ObjectHandleInfo.GrantedAccess,
- DesiredAccess))
- {
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /*
+ * Check if the handle has either FILE_WRITE_DATA or FILE_APPEND_DATA was
+ * granted. However, if this is a named pipe, make sure we don't ask for
+ * FILE_APPEND_DATA as it interferes with the FILE_CREATE_PIPE_INSTANCE
+ * access right!
+ */
+ if (!(ObjectHandleInfo.GrantedAccess &
+ ((!(FileObject->Flags & FO_NAMED_PIPE) ? FILE_APPEND_DATA : 0) |
+ FILE_WRITE_DATA)))
+ {
+ /* We failed */
ObDereferenceObject(FileObject);
return STATUS_ACCESS_DENIED;
}
- /* Check if this is a direct open or not */
- if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
- {
- DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
- }
- else
- {
- DeviceObject = IoGetRelatedDeviceObject(FileObject);
- }
-
/* Check if we should use Sync IO or not */
if (FileObject->Flags & FO_SYNCHRONOUS_IO)
{
- /* Use File Object event */
- KeClearEvent(&FileObject->Event);
+ /* Lock it */
+ IopLockFileObject(FileObject);
}
else
{
/* Use local event */
- KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
+ Event = ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), TAG_IO);
+ KeInitializeEvent(Event, SynchronizationEvent, FALSE);
LocalEvent = TRUE;
}
+ /* Get the Device Object */
+ DeviceObject = IoGetRelatedDeviceObject(FileObject);
+
+ /* Clear the event */
+ KeClearEvent(&FileObject->Event);
+
/* Allocate the IRP */
- if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
- {
- ObDereferenceObject(FileObject);
- return STATUS_INSUFFICIENT_RESOURCES;
- }
+ Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
+ if (!Irp) return IopCleanupFailedIrp(FileObject, NULL);
/* Set up the IRP */
Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
+ Irp->UserIosb = (LocalEvent) ? &KernelIosb : IoStatusBlock;
+ Irp->UserEvent = (LocalEvent) ? Event : NULL;
Irp->RequestorMode = PreviousMode;
- Irp->UserIosb = IoStatusBlock;
- Irp->UserEvent = (LocalEvent) ? &Event : NULL;
Irp->Tail.Overlay.Thread = PsGetCurrentThread();
Irp->Tail.Overlay.OriginalFileObject = FileObject;
+ Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
/* Set up Stack Data */
StackPtr = IoGetNextIrpStackLocation(Irp);
@@ -1028,27 +942,24 @@
StackPtr->FileObject = FileObject;
/* Call the Driver */
- Status = IoCallDriver(DeviceObject, Irp);
- if (Status == STATUS_PENDING)
- {
- if (LocalEvent)
- {
- KeWaitForSingleObject(&Event,
- Executive,
- PreviousMode,
- FileObject->Flags & FO_ALERTABLE_IO,
- NULL);
- Status = IoStatusBlock->Status;
- }
- else
- {
- KeWaitForSingleObject(&FileObject->Event,
- Executive,
- PreviousMode,
- FileObject->Flags & FO_ALERTABLE_IO,
- NULL);
- Status = FileObject->FinalStatus;
- }
+ Status = IopPerformSynchronousRequest(DeviceObject,
+ Irp,
+ FileObject,
+ FALSE,
+ PreviousMode,
+ !LocalEvent,
+ IopOtherTransfer);
+
+ /* Check if this was async I/O */
+ if (LocalEvent)
+ {
+ /* It was, finalize this request */
+ Status = IopFinalizeAsynchronousIo(Status,
+ Event,
+ Irp,
+ PreviousMode,
+ &KernelIosb,
+ IoStatusBlock);
}
/* Return the Status */