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; }
/*