mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
Cleanup ntlock/unlockfile with proper io semantics..same stuff as previous patches
svn path=/trunk/; revision=15269
This commit is contained in:
parent
6f61a478e8
commit
030580a782
1 changed files with 231 additions and 230 deletions
|
@ -30,18 +30,6 @@ SeSetWorldSecurityDescriptor(SECURITY_INFORMATION SecurityInformation,
|
|||
|
||||
/* 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
|
||||
|
@ -1759,150 +1747,132 @@ NtLockFile(IN HANDLE FileHandle,
|
|||
IN PLARGE_INTEGER ByteOffset,
|
||||
IN PLARGE_INTEGER Length,
|
||||
IN PULONG Key,
|
||||
IN BOOLEAN FailImmediatedly,
|
||||
IN BOOLEAN ExclusiveLock
|
||||
)
|
||||
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;
|
||||
PKEVENT Event = NULL;
|
||||
BOOLEAN LocalEvent = FALSE;
|
||||
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
OBJECT_HANDLE_INFORMATION HandleInformation;
|
||||
|
||||
// FIXME: instead of this, use SEH when available?
|
||||
if (!Length || !ByteOffset)
|
||||
{
|
||||
Status = STATUS_INVALID_PARAMETER;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
PreviousMode = ExGetPreviousMode();
|
||||
/* FIXME: instead of this, use SEH */
|
||||
if (!Length || !ByteOffset) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
/* Get File Object */
|
||||
Status = ObReferenceObjectByHandle(FileHandle,
|
||||
0,
|
||||
IoFileObjectType,
|
||||
PreviousMode,
|
||||
(PVOID*)&FileObject,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
&HandleInformation);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
/* Must have FILE_READ_DATA | FILE_WRITE_DATA access */
|
||||
if (!(HandleInformation.GrantedAccess & (FILE_WRITE_DATA | FILE_READ_DATA)))
|
||||
{
|
||||
goto fail;
|
||||
DPRINT1("Invalid access rights\n");
|
||||
ObDereferenceObject(FileObject);
|
||||
return STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
DeviceObject = IoGetRelatedDeviceObject(FileObject);
|
||||
|
||||
Irp = IoAllocateIrp(DeviceObject->StackSize,
|
||||
FALSE);
|
||||
if (Irp == NULL)
|
||||
{
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (EventHandle != NULL && !FailImmediatedly)
|
||||
/* Get Event Object */
|
||||
if (EventHandle)
|
||||
{
|
||||
Status = ObReferenceObjectByHandle(EventHandle,
|
||||
SYNCHRONIZE,
|
||||
EVENT_MODIFY_STATE,
|
||||
ExEventObjectType,
|
||||
PreviousMode,
|
||||
(PVOID *)&Event,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
goto fail;
|
||||
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
|
||||
{
|
||||
Event = &FileObject->Event;
|
||||
KeResetEvent(Event);
|
||||
DeviceObject = IoGetRelatedDeviceObject(FileObject);
|
||||
}
|
||||
|
||||
/* Trigger FileObject/Event dereferencing */
|
||||
Irp->Tail.Overlay.OriginalFileObject = 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;
|
||||
}
|
||||
|
||||
Irp->RequestorMode = PreviousMode;
|
||||
Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
|
||||
Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
|
||||
|
||||
Irp->UserEvent = Event;
|
||||
Irp->UserIosb = IoStatusBlock;
|
||||
Irp->Tail.Overlay.Thread = PsGetCurrentThread();
|
||||
|
||||
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;
|
||||
/* Allocate the IRP */
|
||||
if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
|
||||
{
|
||||
ObDereferenceObject(FileObject);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/* Allocate local buffer */
|
||||
LocalLength = ExAllocatePoolWithTag(NonPagedPool,
|
||||
sizeof(LARGE_INTEGER),
|
||||
TAG_LOCK);
|
||||
if (!LocalLength)
|
||||
{
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto fail;
|
||||
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;
|
||||
|
||||
/* 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;
|
||||
|
||||
IoSetCompletionRoutine(Irp,
|
||||
IopLockFileCompletionRoutine,
|
||||
LocalLength,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE);
|
||||
/* Set Flags */
|
||||
if (FailImmediately) StackPtr->Flags = SL_FAIL_IMMEDIATELY;
|
||||
if (ExclusiveLock) StackPtr->Flags |= SL_EXCLUSIVE_LOCK;
|
||||
|
||||
/* Can't touch FileObject after IoCallDriver since it might be freed */
|
||||
Status = IofCallDriver(DeviceObject, Irp);
|
||||
if (Status == STATUS_PENDING && (FileObject->Flags & FO_SYNCHRONOUS_IO))
|
||||
/* Call the Driver */
|
||||
FileObject->LockOperation = TRUE;
|
||||
Status = IoCallDriver(DeviceObject, Irp);
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
Status = KeWaitForSingleObject(Event,
|
||||
if (!LocalEvent)
|
||||
{
|
||||
KeWaitForSingleObject(&FileObject->Event,
|
||||
Executive,
|
||||
PreviousMode,
|
||||
FileObject->Flags & FO_ALERTABLE_IO,
|
||||
NULL);
|
||||
|
||||
if (Status != STATUS_WAIT_0)
|
||||
{
|
||||
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? */
|
||||
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 the Status */
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -2870,87 +2840,118 @@ NtUnlockFile(IN HANDLE FileHandle,
|
|||
PIRP Irp = NULL;
|
||||
PIO_STACK_LOCATION StackPtr;
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
KPROCESSOR_MODE PreviousMode;
|
||||
NTSTATUS Status;
|
||||
KEVENT Event;
|
||||
BOOLEAN LocalEvent = FALSE;
|
||||
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
OBJECT_HANDLE_INFORMATION HandleInformation;
|
||||
|
||||
// FIXME: instead of this, use SEH when available
|
||||
if (!Length || !ByteOffset)
|
||||
{
|
||||
Status = STATUS_INVALID_PARAMETER;
|
||||
goto fail;
|
||||
}
|
||||
/* FIXME: instead of this, use SEH */
|
||||
if (!Length || !ByteOffset) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
PreviousMode = ExGetPreviousMode();
|
||||
|
||||
/*
|
||||
* BUGBUG: ObReferenceObjectByHandle fails if DesiredAccess=0 and mode=UserMode
|
||||
* It should ONLY fail if we desire an access that conflict with granted access!
|
||||
*/
|
||||
/* Get File Object */
|
||||
Status = ObReferenceObjectByHandle(FileHandle,
|
||||
0, //FILE_READ_DATA,//BUGBUG: have to use something...but shouldn't have to!
|
||||
0,
|
||||
IoFileObjectType,
|
||||
PreviousMode,
|
||||
(PVOID*)&FileObject,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
&HandleInformation);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
/* Must have FILE_READ_DATA | FILE_WRITE_DATA access */
|
||||
if (!(HandleInformation.GrantedAccess & (FILE_WRITE_DATA | FILE_READ_DATA)))
|
||||
{
|
||||
goto fail;
|
||||
DPRINT1("Invalid access rights\n");
|
||||
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);
|
||||
|
||||
Irp = IoAllocateIrp(DeviceObject->StackSize,
|
||||
FALSE);
|
||||
if (Irp == NULL)
|
||||
{
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Trigger FileObject/Event dereferencing */
|
||||
Irp->Tail.Overlay.OriginalFileObject = FileObject;
|
||||
Irp->RequestorMode = PreviousMode;
|
||||
Irp->UserIosb = IoStatusBlock;
|
||||
Irp->Tail.Overlay.Thread = PsGetCurrentThread();
|
||||
/* 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;
|
||||
}
|
||||
|
||||
StackPtr = IoGetNextIrpStackLocation(Irp);
|
||||
StackPtr->MajorFunction = IRP_MJ_LOCK_CONTROL;
|
||||
StackPtr->MinorFunction = IRP_MN_UNLOCK_SINGLE;
|
||||
StackPtr->DeviceObject = DeviceObject;
|
||||
StackPtr->FileObject = FileObject;
|
||||
/* Allocate the IRP */
|
||||
if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
|
||||
{
|
||||
ObDereferenceObject(FileObject);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/* Allocate local buffer */
|
||||
LocalLength = ExAllocatePoolWithTag(NonPagedPool,
|
||||
sizeof(LARGE_INTEGER),
|
||||
TAG_LOCK);
|
||||
if (!LocalLength)
|
||||
{
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto fail;
|
||||
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;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* Allways synchronous */
|
||||
Status = IofCallDriver(DeviceObject, Irp);
|
||||
|
||||
ExFreePool(LocalLength);
|
||||
|
||||
return Status;
|
||||
|
||||
fail:;
|
||||
if (LocalLength)
|
||||
ExFreePool(LocalLength);
|
||||
|
||||
if (Irp)
|
||||
IoFreeIrp(Irp);
|
||||
|
||||
if (FileObject)
|
||||
ObDereferenceObject(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;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the Status */
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue