Author: ion Date: Sun Jul 2 23:01:17 2006 New Revision: 22775
URL: http://svn.reactos.org/svn/reactos?rev=22775&view=rev Log: - NtLockFile: - Add proper sync operation. - Set the APC Routine/Context in the IRP instead of ignoring them. - Dereference the event on failure. - Set the allocated buffer as AuxiliaryBuffer so the I/O manager fres it.
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 Sun Jul 2 23:01:17 2006 @@ -1059,7 +1059,7 @@ }
/* - * @unimplemented + * @implemented */ NTSTATUS NTAPI @@ -1074,19 +1074,18 @@ IN BOOLEAN FailImmediately, IN BOOLEAN ExclusiveLock) { - PFILE_OBJECT FileObject = NULL; + PFILE_OBJECT FileObject; PLARGE_INTEGER LocalLength = NULL; PIRP Irp = NULL; PIO_STACK_LOCATION StackPtr; PDEVICE_OBJECT DeviceObject; PKEVENT Event = NULL; - BOOLEAN LocalEvent = FALSE; + BOOLEAN LockedForSync = FALSE; KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); LARGE_INTEGER CapturedByteOffset, CapturedLength; NTSTATUS Status = STATUS_SUCCESS; OBJECT_HANDLE_INFORMATION HandleInformation; PAGED_CODE(); - CapturedByteOffset.QuadPart = 0; CapturedLength.QuadPart = 0;
@@ -1099,96 +1098,83 @@ &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))) - { - DPRINT1("Invalid access rights\n"); + /* 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; }
- /* Get Event Object */ + /* Check if we have an event handle */ if (EventHandle) { + /* Reference it */ Status = ObReferenceObjectByHandle(EventHandle, EVENT_MODIFY_STATE, ExEventObjectType, PreviousMode, (PVOID *)&Event, NULL); - if (Status != STATUS_SUCCESS) return(Status); + if (Status != STATUS_SUCCESS) return Status; KeClearEvent(Event); }
- /* Check if this is a direct open or not */ - if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN) - { - DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject); - } - else - { - DeviceObject = IoGetRelatedDeviceObject(FileObject); - } + /* Get the device object */ + 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); - } - else - { - LocalEvent = TRUE; - } + /* Lock it */ + IopLockFileObject(FileObject); + LockedForSync = TRUE; + } + + /* Clear File Object event */ + KeClearEvent(&FileObject->Event); + FileObject->LockOperation = TRUE;
/* Allocate the IRP */ Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); - if (!Irp) - { - ObDereferenceObject(FileObject); - return STATUS_INSUFFICIENT_RESOURCES; - } - - /* Allocate local buffer */ - LocalLength = ExAllocatePoolWithTag(NonPagedPool, - sizeof(LARGE_INTEGER), - TAG_LOCK); - if (!LocalLength) - { - IoFreeIrp(Irp); - ObDereferenceObject(FileObject); - return STATUS_INSUFFICIENT_RESOURCES; - } - *LocalLength = CapturedLength; + if (!Irp) return IopCleanupFailedIrp(FileObject, Event);
/* Set up the IRP */ Irp->RequestorMode = PreviousMode; @@ -1196,6 +1182,8 @@ Irp->UserEvent = Event; Irp->Tail.Overlay.Thread = PsGetCurrentThread(); Irp->Tail.Overlay.OriginalFileObject = FileObject; + Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine; + Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
/* Set up Stack Data */ StackPtr = IoGetNextIrpStackLocation(Irp); @@ -1203,7 +1191,24 @@ StackPtr->MinorFunction = IRP_MN_LOCK; StackPtr->FileObject = FileObject;
+ /* Allocate local buffer */ + LocalLength = ExAllocatePoolWithTag(NonPagedPool, + sizeof(LARGE_INTEGER), + TAG_LOCK); + if (!LocalLength) + { + /* Fail */ + IoFreeIrp(Irp); + if (Event) ObDereferenceObject(Event); + ObDereferenceObject(FileObject); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* Set the length */ + *LocalLength = CapturedLength; + /* Set Parameters */ + Irp->Tail.Overlay.AuxiliaryBuffer = (PVOID)LocalLength; StackPtr->Parameters.LockControl.Length = LocalLength; StackPtr->Parameters.LockControl.ByteOffset = CapturedByteOffset; StackPtr->Parameters.LockControl.Key = Key; @@ -1212,24 +1217,14 @@ if (FailImmediately) StackPtr->Flags = SL_FAIL_IMMEDIATELY; if (ExclusiveLock) StackPtr->Flags |= SL_EXCLUSIVE_LOCK;
- /* Call the Driver */ - FileObject->LockOperation = TRUE; - Status = IoCallDriver(DeviceObject, Irp); - if (Status == STATUS_PENDING) - { - if (!LocalEvent) - { - KeWaitForSingleObject(&FileObject->Event, - Executive, - PreviousMode, - FileObject->Flags & FO_ALERTABLE_IO, - NULL); - Status = FileObject->FinalStatus; - } - } - - /* Return the Status */ - return Status; + /* Perform the call */ + return IopPerformSynchronousRequest(DeviceObject, + Irp, + FileObject, + FALSE, + PreviousMode, + LockedForSync, + IopOtherTransfer); }
/*