Author: ion
Date: Mon Jul 3 02:07:20 2006
New Revision: 22786
URL:
http://svn.reactos.org/svn/reactos?rev=22786&view=rev
Log:
- Add proper sync handling to NtUnlockFile.
Modified:
trunk/reactos/ntoskrnl/io/iomgr/iofunc.c
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 Mon Jul 3 02:07:20 2006
@@ -20,6 +20,17 @@
__FUNCTION__,
Irp);
#endif
+
+///
+//
+// TODO:
+// - Lock/Unlock <= DONE
+// - Query/Set Volume Info
+// - Read/Write file
+// - QuerySet/ File Info
+// - NtQueryDirectoryFile
+//
+///
/* PRIVATE FUNCTIONS *********************************************************/
@@ -1104,8 +1115,8 @@
IN BOOLEAN ExclusiveLock)
{
PFILE_OBJECT FileObject;
- PLARGE_INTEGER LocalLength = NULL;
- PIRP Irp = NULL;
+ PLARGE_INTEGER LocalLength;
+ PIRP Irp;
PIO_STACK_LOCATION StackPtr;
PDEVICE_OBJECT DeviceObject;
PKEVENT Event = NULL;
@@ -2231,19 +2242,19 @@
IN PLARGE_INTEGER Length,
IN ULONG Key OPTIONAL)
{
- PFILE_OBJECT FileObject = NULL;
- PLARGE_INTEGER LocalLength = NULL;
- PIRP Irp = NULL;
+ PFILE_OBJECT FileObject;
+ PLARGE_INTEGER LocalLength;
+ PIRP Irp;
PIO_STACK_LOCATION StackPtr;
PDEVICE_OBJECT DeviceObject;
- KEVENT Event;
+ PKEVENT Event = NULL;
BOOLEAN LocalEvent = FALSE;
KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
+ LARGE_INTEGER CapturedByteOffset, CapturedLength;
NTSTATUS Status = STATUS_SUCCESS;
- LARGE_INTEGER CapturedByteOffset, CapturedLength;
OBJECT_HANDLE_INFORMATION HandleInformation;
+ IO_STATUS_BLOCK KernelIosb;
PAGED_CODE();
-
CapturedByteOffset.QuadPart = 0;
CapturedLength.QuadPart = 0;
@@ -2256,38 +2267,47 @@
&HandleInformation);
if (!NT_SUCCESS(Status)) return Status;
+ /* Check if we're called from user mode */
if (PreviousMode != KernelMode)
{
- /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access unless we're
- in KernelMode! */
- if (!(HandleInformation.GrantedAccess & (FILE_WRITE_DATA | FILE_READ_DATA)))
+ /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
+ if (!(HandleInformation.GrantedAccess &
+ (FILE_WRITE_DATA | FILE_READ_DATA)))
{
ObDereferenceObject(FileObject);
return STATUS_ACCESS_DENIED;
}
+ /* Enter SEH for probing */
_SEH_TRY
{
+ /* Probe the I/O Status block */
ProbeForWrite(IoStatusBlock,
sizeof(IO_STATUS_BLOCK),
sizeof(ULONG));
+
+ /* Probe and capture the large integers */
CapturedByteOffset = ProbeForReadLargeInteger(ByteOffset);
CapturedLength = ProbeForReadLargeInteger(Length);
}
_SEH_HANDLE
{
+ /* Get the exception code */
Status = _SEH_GetExceptionCode();
}
_SEH_END;
+ /* Check if probing failed */
if (!NT_SUCCESS(Status))
{
+ /* Dereference the object and return exception code */
ObDereferenceObject(FileObject);
return Status;
}
}
else
{
+ /* Otherwise, capture them directly */
CapturedByteOffset = *ByteOffset;
CapturedLength = *Length;
}
@@ -2305,23 +2325,38 @@
/* 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;
}
+
+ /* Clear File Object event */
+ KeClearEvent(&FileObject->Event);
/* Allocate the IRP */
Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
- if (!Irp)
- {
- ObDereferenceObject(FileObject);
- return STATUS_INSUFFICIENT_RESOURCES;
- }
+ if (!Irp) return IopCleanupFailedIrp(FileObject, Event);
+
+ /* Set up the IRP */
+ Irp->RequestorMode = PreviousMode;
+ Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
+ Irp->UserIosb = (LocalEvent) ? &KernelIosb : 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);
+ StackPtr->MajorFunction = IRP_MJ_LOCK_CONTROL;
+ StackPtr->MinorFunction = IRP_MN_UNLOCK_SINGLE;
+ StackPtr->FileObject = FileObject;
/* Allocate local buffer */
LocalLength = ExAllocatePoolWithTag(NonPagedPool,
@@ -2329,56 +2364,44 @@
TAG_LOCK);
if (!LocalLength)
{
+ /* Fail */
IoFreeIrp(Irp);
+ if (Event) ObDereferenceObject(Event);
ObDereferenceObject(FileObject);
return STATUS_INSUFFICIENT_RESOURCES;
}
+
+ /* Set the length */
*LocalLength = CapturedLength;
- /* Set up the IRP */
- Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
- Irp->RequestorMode = PreviousMode;
- Irp->UserIosb = IoStatusBlock;
- Irp->UserEvent = (LocalEvent) ? &Event : NULL;
- Irp->Tail.Overlay.Thread = PsGetCurrentThread();
- Irp->Tail.Overlay.OriginalFileObject = FileObject;
-
- /* Set up Stack Data */
- StackPtr = IoGetNextIrpStackLocation(Irp);
- StackPtr->MajorFunction = IRP_MJ_LOCK_CONTROL;
- StackPtr->MinorFunction = IRP_MN_UNLOCK_SINGLE;
- StackPtr->FileObject = FileObject;
-
/* Set Parameters */
+ Irp->Tail.Overlay.AuxiliaryBuffer = (PVOID)LocalLength;
StackPtr->Parameters.LockControl.Length = LocalLength;
StackPtr->Parameters.LockControl.ByteOffset = CapturedByteOffset;
StackPtr->Parameters.LockControl.Key = Key;
/* 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;
- }
- }
-
- /* Return the Status */
+ 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 status */
return Status;
}