Cleanup ntlock/unlockfile with proper io semantics..same stuff as
previous patches
Modified: trunk/reactos/ntoskrnl/io/file.c
_____
Modified: trunk/reactos/ntoskrnl/io/file.c
--- trunk/reactos/ntoskrnl/io/file.c 2005-05-13 19:47:30 UTC (rev
15268)
+++ trunk/reactos/ntoskrnl/io/file.c 2005-05-13 21:07:40 UTC (rev
15269)
@@ -30,18 +30,6 @@
/* INTERNAL FUNCTIONS
********************************************************/
-static
-NTSTATUS
-STDCALL
-IopLockFileCompletionRoutine(IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp,
- IN PVOID Context)
-{
- ExFreePool(Context);
- return STATUS_SUCCESS;
- // FIXME: Should I call IoFreeIrp and return
STATUS_MORE_PROCESSING_REQUIRED?
-}
-
/*
* NAME INTERNAL
* IopCreateFile
@@ -1751,159 +1739,141 @@
*/
NTSTATUS
STDCALL
-NtLockFile(IN HANDLE FileHandle,
- IN HANDLE EventHandle OPTIONAL,
- IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
- IN PVOID ApcContext OPTIONAL,
+NtLockFile(IN HANDLE FileHandle,
+ IN HANDLE EventHandle OPTIONAL,
+ IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
+ IN PVOID ApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK IoStatusBlock,
- IN PLARGE_INTEGER ByteOffset,
- IN PLARGE_INTEGER Length,
- IN PULONG Key,
- IN BOOLEAN FailImmediatedly,
- IN BOOLEAN ExclusiveLock
- )
+ IN PLARGE_INTEGER ByteOffset,
+ IN PLARGE_INTEGER Length,
+ IN PULONG Key,
+ IN BOOLEAN FailImmediately,
+ IN BOOLEAN ExclusiveLock)
{
- PFILE_OBJECT FileObject = NULL;
- PLARGE_INTEGER LocalLength = NULL;
- PKEVENT Event = NULL;
- PIRP Irp = NULL;
- PIO_STACK_LOCATION StackPtr;
- PDEVICE_OBJECT DeviceObject;
- KPROCESSOR_MODE PreviousMode;
- NTSTATUS Status;
+ PFILE_OBJECT FileObject = NULL;
+ PLARGE_INTEGER LocalLength = NULL;
+ PIRP Irp = NULL;
+ PIO_STACK_LOCATION StackPtr;
+ PDEVICE_OBJECT DeviceObject;
+ PKEVENT Event = NULL;
+ BOOLEAN LocalEvent = FALSE;
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ NTSTATUS Status = STATUS_SUCCESS;
+ OBJECT_HANDLE_INFORMATION HandleInformation;
+
+ /* FIXME: instead of this, use SEH */
+ if (!Length || !ByteOffset) return STATUS_INVALID_PARAMETER;
- // FIXME: instead of this, use SEH when available?
- if (!Length || !ByteOffset)
- {
- Status = STATUS_INVALID_PARAMETER;
- goto fail;
- }
+ /* Get File Object */
+ Status = ObReferenceObjectByHandle(FileHandle,
+ 0,
+ IoFileObjectType,
+ PreviousMode,
+ (PVOID*)&FileObject,
+ &HandleInformation);
+ if (!NT_SUCCESS(Status)) return Status;
- PreviousMode = ExGetPreviousMode();
+ /* Must have FILE_READ_DATA | FILE_WRITE_DATA access */
+ if (!(HandleInformation.GrantedAccess & (FILE_WRITE_DATA |
FILE_READ_DATA)))
+ {
+ DPRINT1("Invalid access rights\n");
+ ObDereferenceObject(FileObject);
+ return STATUS_ACCESS_DENIED;
+ }
- Status = ObReferenceObjectByHandle(FileHandle,
- 0,
- IoFileObjectType,
- PreviousMode,
- (PVOID*)&FileObject,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- goto fail;
- }
+ /* Get Event Object */
+ if (EventHandle)
+ {
+ Status = ObReferenceObjectByHandle(EventHandle,
+ EVENT_MODIFY_STATE,
+ ExEventObjectType,
+ PreviousMode,
+ (PVOID *)&Event,
+ NULL);
+ if (Status != STATUS_SUCCESS) return(Status);
+ KeClearEvent(Event);
+ }
- DeviceObject = IoGetRelatedDeviceObject(FileObject);
+ /* Check if this is a direct open or not */
+ if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
+ {
+ DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
+ }
+ else
+ {
+ DeviceObject = IoGetRelatedDeviceObject(FileObject);
+ }
- Irp = IoAllocateIrp(DeviceObject->StackSize,
- FALSE);
- if (Irp == NULL)
- {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto fail;
- }
+ /* 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;
+ }
- if (EventHandle != NULL && !FailImmediatedly)
- {
- Status = ObReferenceObjectByHandle(EventHandle,
- SYNCHRONIZE,
- ExEventObjectType,
- PreviousMode,
- (PVOID*)&Event,
- NULL);
- if (!NT_SUCCESS(Status))
+ /* Allocate the IRP */
+ if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
{
- goto fail;
+ ObDereferenceObject(FileObject);
+ return STATUS_INSUFFICIENT_RESOURCES;
}
- }
- else
- {
- Event = &FileObject->Event;
- KeResetEvent(Event);
- }
- /* Trigger FileObject/Event dereferencing */
- Irp->Tail.Overlay.OriginalFileObject = FileObject;
+ /* Allocate local buffer */
+ LocalLength = ExAllocatePoolWithTag(NonPagedPool,
+ sizeof(LARGE_INTEGER),
+ TAG_LOCK);
+ if (!LocalLength)
+ {
+ IoFreeIrp(Irp);
+ ObDereferenceObject(FileObject);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ *LocalLength = *Length;
+
+ /* Set up the IRP */
+ Irp->RequestorMode = PreviousMode;
+ Irp->UserIosb = IoStatusBlock;
+ Irp->UserEvent = Event;
+ Irp->Tail.Overlay.Thread = PsGetCurrentThread();
+ Irp->Tail.Overlay.OriginalFileObject = FileObject;
- Irp->RequestorMode = PreviousMode;
- Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
- Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
+ /* Set up Stack Data */
+ StackPtr = IoGetNextIrpStackLocation(Irp);
+ StackPtr->MajorFunction = IRP_MJ_LOCK_CONTROL;
+ StackPtr->MinorFunction = IRP_MN_LOCK;
+ StackPtr->FileObject = FileObject;
+
+ /* Set Parameters */
+ StackPtr->Parameters.LockControl.Length = LocalLength;
+ StackPtr->Parameters.LockControl.ByteOffset = *ByteOffset;
+ StackPtr->Parameters.LockControl.Key = Key ? *Key : 0;
- Irp->UserEvent = Event;
- Irp->UserIosb = IoStatusBlock;
- Irp->Tail.Overlay.Thread = PsGetCurrentThread();
+ /* Set Flags */
+ if (FailImmediately) StackPtr->Flags = SL_FAIL_IMMEDIATELY;
+ if (ExclusiveLock) StackPtr->Flags |= SL_EXCLUSIVE_LOCK;
- StackPtr = IoGetNextIrpStackLocation(Irp);
- StackPtr->MajorFunction = IRP_MJ_LOCK_CONTROL;
- StackPtr->MinorFunction = IRP_MN_LOCK;
- StackPtr->FileObject = FileObject;
-
- if (ExclusiveLock)
- StackPtr->Flags |= SL_EXCLUSIVE_LOCK;
-
- if (FailImmediatedly)
- StackPtr->Flags |= SL_FAIL_IMMEDIATELY;
-
- LocalLength = ExAllocatePoolWithTag(NonPagedPool,
- sizeof(LARGE_INTEGER),
- TAG_LOCK);
- if (!LocalLength)
- {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto fail;
- }
-
- *LocalLength = *Length;
-
- StackPtr->Parameters.LockControl.Length = LocalLength;
- StackPtr->Parameters.LockControl.ByteOffset = *ByteOffset;
- StackPtr->Parameters.LockControl.Key = Key ? *Key : 0;
-
- IoSetCompletionRoutine(Irp,
- IopLockFileCompletionRoutine,
- LocalLength,
- TRUE,
- TRUE,
- TRUE);
-
- /* Can't touch FileObject after IoCallDriver since it might be freed
*/
- Status = IofCallDriver(DeviceObject, Irp);
- if (Status == STATUS_PENDING && (FileObject->Flags &
FO_SYNCHRONOUS_IO))
- {
- Status = KeWaitForSingleObject(Event,
- Executive,
- PreviousMode,
- FileObject->Flags & FO_ALERTABLE_IO,
- NULL);
-
- if (Status != STATUS_WAIT_0)
+ /* Call the Driver */
+ FileObject->LockOperation = TRUE;
+ Status = IoCallDriver(DeviceObject, Irp);
+ if (Status == STATUS_PENDING)
{
- DPRINT1("NtLockFile -> KeWaitForSingleObject failed!\n");
- /*
- * FIXME: Should do some special processing here if alertable
wait
- * was interupted by user apc or a thread alert (STATUS_ALERTED,
STATUS_USER_APC)
- */
- return Status; /* Set status to something else? */
+ if (!LocalEvent)
+ {
+ KeWaitForSingleObject(&FileObject->Event,
+ Executive,
+ PreviousMode,
+ FileObject->Flags & FO_ALERTABLE_IO,
+ NULL);
+ Status = FileObject->FinalStatus;
+ }
}
- Status = IoStatusBlock->Status;
- }
-
- return Status;
-
-fail:;
- if (LocalLength)
- ExFreePool(LocalLength);
-
- if (Irp)
- IoFreeIrp(Irp);
-
- if (Event)
- ObDereferenceObject(Event);
-
- if (FileObject)
- ObDereferenceObject(FileObject);
-
- return Status;
+ /* Return the Status */
+ return Status;
}
/*
@@ -2865,93 +2835,124 @@
IN PLARGE_INTEGER Length,
OUT PULONG Key OPTIONAL)
{
- PFILE_OBJECT FileObject = NULL;
- PLARGE_INTEGER LocalLength = NULL;
- PIRP Irp = NULL;
- PIO_STACK_LOCATION StackPtr;
- PDEVICE_OBJECT DeviceObject;
- KPROCESSOR_MODE PreviousMode;
- NTSTATUS Status;
+ PFILE_OBJECT FileObject = NULL;
+ PLARGE_INTEGER LocalLength = NULL;
+ PIRP Irp = NULL;
+ PIO_STACK_LOCATION StackPtr;
+ PDEVICE_OBJECT DeviceObject;
+ KEVENT Event;
+ BOOLEAN LocalEvent = FALSE;
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ NTSTATUS Status = STATUS_SUCCESS;
+ OBJECT_HANDLE_INFORMATION HandleInformation;
+
+ /* FIXME: instead of this, use SEH */
+ if (!Length || !ByteOffset) return STATUS_INVALID_PARAMETER;
- // FIXME: instead of this, use SEH when available
- if (!Length || !ByteOffset)
- {
- Status = STATUS_INVALID_PARAMETER;
- goto fail;
- }
+ /* Get File Object */
+ Status = ObReferenceObjectByHandle(FileHandle,
+ 0,
+ IoFileObjectType,
+ PreviousMode,
+ (PVOID*)&FileObject,
+ &HandleInformation);
+ if (!NT_SUCCESS(Status)) return Status;
- PreviousMode = ExGetPreviousMode();
+ /* Must have FILE_READ_DATA | FILE_WRITE_DATA access */
+ if (!(HandleInformation.GrantedAccess & (FILE_WRITE_DATA |
FILE_READ_DATA)))
+ {
+ DPRINT1("Invalid access rights\n");
+ ObDereferenceObject(FileObject);
+ return STATUS_ACCESS_DENIED;
+ }
- /*
- * BUGBUG: ObReferenceObjectByHandle fails if DesiredAccess=0 and
mode=UserMode
- * It should ONLY fail if we desire an access that conflict with
granted access!
- */
- Status = ObReferenceObjectByHandle(FileHandle,
- 0, //FILE_READ_DATA,//BUGBUG: have to use something...but
shouldn't have to!
- IoFileObjectType,
- PreviousMode,
- (PVOID*)&FileObject,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- goto fail;
- }
+ /* Check if this is a direct open or not */
+ if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
+ {
+ DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
+ }
+ else
+ {
+ DeviceObject = IoGetRelatedDeviceObject(FileObject);
+ }
- 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
+ {
+ /* Use local event */
+ KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
+ LocalEvent = TRUE;
+ }
- Irp = IoAllocateIrp(DeviceObject->StackSize,
- FALSE);
- if (Irp == NULL)
- {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto fail;
- }
+ /* Allocate the IRP */
+ if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
+ {
+ ObDereferenceObject(FileObject);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
- /* Trigger FileObject/Event dereferencing */
- Irp->Tail.Overlay.OriginalFileObject = FileObject;
- Irp->RequestorMode = PreviousMode;
- Irp->UserIosb = IoStatusBlock;
- Irp->Tail.Overlay.Thread = PsGetCurrentThread();
+ /* Allocate local buffer */
+ LocalLength = ExAllocatePoolWithTag(NonPagedPool,
+ sizeof(LARGE_INTEGER),
+ TAG_LOCK);
+ if (!LocalLength)
+ {
+ IoFreeIrp(Irp);
+ ObDereferenceObject(FileObject);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ *LocalLength = *Length;
+
+ /* 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;
- StackPtr = IoGetNextIrpStackLocation(Irp);
- StackPtr->MajorFunction = IRP_MJ_LOCK_CONTROL;
- StackPtr->MinorFunction = IRP_MN_UNLOCK_SINGLE;
- StackPtr->DeviceObject = DeviceObject;
- StackPtr->FileObject = 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 */
+ StackPtr->Parameters.LockControl.Length = LocalLength;
+ StackPtr->Parameters.LockControl.ByteOffset = *ByteOffset;
+ StackPtr->Parameters.LockControl.Key = Key ? *Key : 0;
- LocalLength = ExAllocatePoolWithTag(NonPagedPool,
- sizeof(LARGE_INTEGER),
- TAG_LOCK);
- if (!LocalLength)
- {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto fail;
- }
+ /* 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;
+ }
+ }
- *LocalLength = *Length;
-
- StackPtr->Parameters.LockControl.Length = LocalLength;
- StackPtr->Parameters.LockControl.ByteOffset = *ByteOffset;
- StackPtr->Parameters.LockControl.Key = Key ? *Key : 0;
-
- /* Allways synchronous */
- Status = IofCallDriver(DeviceObject, Irp);
-
- ExFreePool(LocalLength);
-
- return Status;
-
-fail:;
- if (LocalLength)
- ExFreePool(LocalLength);
-
- if (Irp)
- IoFreeIrp(Irp);
-
- if (FileObject)
- ObDereferenceObject(FileObject);
-
- return Status;
+ /* Return the Status */
+ return Status;
}
/*