- Implement file locking
CORE-10790 #resolve

svn path=/trunk/; revision=71130
This commit is contained in:
Thomas Faber 2016-04-09 19:33:42 +00:00
parent b05fcc754d
commit 2063cc07b6
6 changed files with 62 additions and 8 deletions

View file

@ -96,6 +96,7 @@ DriverEntry(PDRIVER_OBJECT DriverObject,
DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = CdfsFsdDispatch;
DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = CdfsFsdDispatch;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = CdfsFsdDispatch;
DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] = CdfsFsdDispatch;
CdfsGlobalData->FastIoDispatch.SizeOfFastIoDispatch = sizeof(FAST_IO_DISPATCH);
CdfsGlobalData->FastIoDispatch.FastIoCheckIfPossible = CdfsFastIoCheckIfPossible;

View file

@ -220,6 +220,7 @@ typedef struct _FCB
ERESOURCE NameListResource;
LIST_ENTRY ShortNameList;
FILE_LOCK FileLock;
} FCB, *PFCB;

View file

@ -35,18 +35,20 @@
/* FUNCTIONS ****************************************************************/
static NTSTATUS
CdfsCleanupFile(PDEVICE_EXTENSION DeviceExt,
CdfsCleanupFile(PCDFS_IRP_CONTEXT IrpContext,
PFILE_OBJECT FileObject)
/*
* FUNCTION: Cleans up after a file has been closed.
*/
{
PDEVICE_EXTENSION DeviceExt;
PFCB Fcb;
DPRINT("CdfsCleanupFile(DeviceExt %p, FileObject %p)\n",
DeviceExt,
FileObject);
DeviceExt = IrpContext->DeviceObject->DeviceExtension;
Fcb = FileObject->FsContext;
if (!Fcb)
{
@ -58,6 +60,15 @@ CdfsCleanupFile(PDEVICE_EXTENSION DeviceExt,
&(DeviceExt->NotifyList),
FileObject->FsContext2);
if (!CdfsFCBIsDirectory(Fcb) &&
FsRtlAreThereCurrentFileLocks(&Fcb->FileLock))
{
FsRtlFastUnlockAll(&Fcb->FileLock,
FileObject,
IoGetRequestorProcess(IrpContext->Irp),
NULL);
}
/* Uninitialize file cache if initialized for this file object. */
if (FileObject->SectionObjectPointer && FileObject->SectionObjectPointer->SharedCacheMap)
{
@ -99,7 +110,7 @@ CdfsCleanup(
KeEnterCriticalRegion();
ExAcquireResourceExclusiveLite(&DeviceExtension->DirResource, TRUE);
Status = CdfsCleanupFile(DeviceExtension, FileObject);
Status = CdfsCleanupFile(IrpContext, FileObject);
ExReleaseResourceLite(&DeviceExtension->DirResource);
KeLeaveCriticalRegion();

View file

@ -53,6 +53,34 @@ CdfsQueueRequest(PCDFS_IRP_CONTEXT IrpContext)
return STATUS_PENDING;
}
static
NTSTATUS
CdfsLockControl(
IN PCDFS_IRP_CONTEXT IrpContext)
{
PFCB Fcb;
NTSTATUS Status;
DPRINT("CdfsLockControl(IrpContext %p)\n", IrpContext);
if (IrpContext->DeviceObject == CdfsGlobalData->DeviceObject)
{
return STATUS_INVALID_DEVICE_REQUEST;
}
Fcb = IrpContext->FileObject->FsContext;
if (CdfsFCBIsDirectory(Fcb))
{
return STATUS_INVALID_PARAMETER;
}
IrpContext->Flags &= ~IRPCONTEXT_COMPLETE;
Status = FsRtlProcessFileLock(&Fcb->FileLock,
IrpContext->Irp,
NULL);
return Status;
}
static
NTSTATUS
CdfsDispatch(PCDFS_IRP_CONTEXT IrpContext)
@ -115,6 +143,10 @@ CdfsDispatch(PCDFS_IRP_CONTEXT IrpContext)
case IRP_MJ_FILE_SYSTEM_CONTROL:
Status = CdfsFileSystemControl(IrpContext);
break;
case IRP_MJ_LOCK_CONTROL:
Status = CdfsLockControl(IrpContext);
break;
}
ASSERT((!(IrpContext->Flags & IRPCONTEXT_COMPLETE) && !(IrpContext->Flags & IRPCONTEXT_QUEUE)) ||

View file

@ -97,6 +97,7 @@ CdfsCreateFCB(PCWSTR FileName)
Fcb->RFCB.Resource = &Fcb->MainResource;
Fcb->RFCB.IsFastIoPossible = FastIoIsNotPossible;
InitializeListHead(&Fcb->ShortNameList);
FsRtlInitializeFileLock(&Fcb->FileLock, NULL, NULL);
return(Fcb);
}
@ -107,6 +108,7 @@ CdfsDestroyFCB(PFCB Fcb)
{
PLIST_ENTRY Entry;
FsRtlUninitializeFileLock(&Fcb->FileLock);
ExDeleteResourceLite(&Fcb->PagingIoResource);
ExDeleteResourceLite(&Fcb->MainResource);

View file

@ -41,7 +41,7 @@
/* FUNCTIONS ****************************************************************/
static NTSTATUS
CdfsReadFile(PDEVICE_EXTENSION DeviceExt,
CdfsReadFile(PCDFS_IRP_CONTEXT IrpContext,
PFILE_OBJECT FileObject,
PUCHAR Buffer,
ULONG Length,
@ -53,6 +53,7 @@ CdfsReadFile(PDEVICE_EXTENSION DeviceExt,
*/
{
NTSTATUS Status = STATUS_SUCCESS;
PDEVICE_EXTENSION DeviceExt;
PFCB Fcb;
ULONG ToRead = Length;
@ -63,6 +64,7 @@ CdfsReadFile(PDEVICE_EXTENSION DeviceExt,
if (Length == 0)
return(STATUS_SUCCESS);
DeviceExt = IrpContext->DeviceObject->DeviceExtension;
Fcb = (PFCB)FileObject->FsContext;
if (ReadOffset >= Fcb->Entry.DataLengthL)
@ -71,6 +73,15 @@ CdfsReadFile(PDEVICE_EXTENSION DeviceExt,
if (ReadOffset + Length > Fcb->Entry.DataLengthL)
ToRead = Fcb->Entry.DataLengthL - ReadOffset;
if (!(IrpFlags & IRP_PAGING_IO) &&
FsRtlAreThereCurrentFileLocks(&Fcb->FileLock))
{
if (!FsRtlCheckLockForReadAccess(&Fcb->FileLock, IrpContext->Irp))
{
return STATUS_FILE_LOCK_CONFLICT;
}
}
DPRINT("Reading %u bytes at %u\n", Length, ReadOffset);
if (!(IrpFlags & (IRP_NOCACHE|IRP_PAGING_IO)))
@ -179,8 +190,6 @@ CdfsRead(
PCDFS_IRP_CONTEXT IrpContext)
{
PIRP Irp;
PDEVICE_OBJECT DeviceObject;
PDEVICE_EXTENSION DeviceExt;
PIO_STACK_LOCATION Stack;
PFILE_OBJECT FileObject;
PVOID Buffer = NULL;
@ -194,17 +203,15 @@ CdfsRead(
ASSERT(IrpContext);
Irp = IrpContext->Irp;
DeviceObject = IrpContext->DeviceObject;
Stack = IrpContext->Stack;
DeviceExt = DeviceObject->DeviceExtension;
FileObject = Stack->FileObject;
ReadLength = Stack->Parameters.Read.Length;
ReadOffset = Stack->Parameters.Read.ByteOffset;
if (ReadLength) Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
Status = CdfsReadFile(DeviceExt,
Status = CdfsReadFile(IrpContext,
FileObject,
Buffer,
ReadLength,