mirror of
https://github.com/winfsp/winfsp.git
synced 2025-07-25 20:13:21 -05:00
sys,dll,inc: implement user mode locking
This commit is contained in:
@@ -162,6 +162,7 @@ FSP_API NTSTATUS FspFileSystemCreate(PWSTR DevicePath,
|
||||
FileSystem->Operations[FspFsctlTransactSetVolumeInformationKind] = FspFileSystemOpSetVolumeInformation;
|
||||
FileSystem->Operations[FspFsctlTransactQueryDirectoryKind] = FspFileSystemOpQueryDirectory;
|
||||
FileSystem->Operations[FspFsctlTransactFileSystemControlKind] = FspFileSystemOpFileSystemControl;
|
||||
FileSystem->Operations[FspFsctlTransactLockControlKind] = FspFileSystemOpLockControl;
|
||||
FileSystem->Operations[FspFsctlTransactQuerySecurityKind] = FspFileSystemOpQuerySecurity;
|
||||
FileSystem->Operations[FspFsctlTransactSetSecurityKind] = FspFileSystemOpSetSecurity;
|
||||
FileSystem->Operations[FspFsctlTransactQueryStreamInformationKind] = FspFileSystemOpQueryStreamInformation;
|
||||
@@ -688,3 +689,8 @@ FSP_API UINT32 FspFileSystemOperationProcessIdF(VOID)
|
||||
{
|
||||
return FspFileSystemOperationProcessId();
|
||||
}
|
||||
|
||||
FSP_API UINT64 FspFileSystemOperationLockOwnerF(VOID)
|
||||
{
|
||||
return FspFileSystemOperationLockOwner();
|
||||
}
|
||||
|
@@ -886,6 +886,7 @@ FSP_API NTSTATUS FspFileSystemOpCleanup(FSP_FILE_SYSTEM *FileSystem,
|
||||
(0 != Request->Req.Cleanup.SetArchiveBit ? FspCleanupSetArchiveBit : 0) |
|
||||
(0 != Request->Req.Cleanup.SetLastAccessTime ? FspCleanupSetLastAccessTime : 0) |
|
||||
(0 != Request->Req.Cleanup.SetLastWriteTime ? FspCleanupSetLastWriteTime : 0) |
|
||||
(0 != Request->Req.Cleanup.UnlockAll ? FspCleanupUnlockAll : 0) |
|
||||
(0 != Request->Req.Cleanup.SetChangeTime ? FspCleanupSetChangeTime : 0));
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
@@ -1247,6 +1248,43 @@ FSP_API NTSTATUS FspFileSystemOpFileSystemControl(FSP_FILE_SYSTEM *FileSystem,
|
||||
return Result;
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspFileSystemOpLockControl(FSP_FILE_SYSTEM *FileSystem,
|
||||
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response)
|
||||
{
|
||||
NTSTATUS Result;
|
||||
|
||||
Result = STATUS_INVALID_DEVICE_REQUEST;
|
||||
switch (Request->Req.LockControl.LockFunction)
|
||||
{
|
||||
case 0x01/*IRP_MN_LOCK*/:
|
||||
if (0 != FileSystem->Interface->Lock)
|
||||
Result = FileSystem->Interface->Lock(FileSystem,
|
||||
(PVOID)ValOfFileContext(Request->Req.LockControl),
|
||||
Request->Req.LockControl.Offset, Request->Req.LockControl.Length,
|
||||
((UINT64)Request->Req.LockControl.ProcessId << 32) | (UINT64)Request->Req.LockControl.Key,
|
||||
0 != Request->Req.LockControl.Exclusive,
|
||||
0 != Request->Req.LockControl.FailImmediately);
|
||||
break;
|
||||
case 0x02/*IRP_MN_UNLOCK_SINGLE*/:
|
||||
if (0 != FileSystem->Interface->Unlock)
|
||||
Result = FileSystem->Interface->Unlock(FileSystem,
|
||||
(PVOID)ValOfFileContext(Request->Req.LockControl),
|
||||
Request->Req.LockControl.Offset, Request->Req.LockControl.Length,
|
||||
((UINT64)Request->Req.LockControl.ProcessId << 32) | (UINT64)Request->Req.LockControl.Key);
|
||||
break;
|
||||
case 0x03/*IRP_MN_UNLOCK_ALL*/:
|
||||
case 0x04/*IRP_MN_UNLOCK_ALL_BY_KEY*/:
|
||||
if (0 != FileSystem->Interface->Unlock)
|
||||
Result = FileSystem->Interface->Unlock(FileSystem,
|
||||
(PVOID)ValOfFileContext(Request->Req.LockControl),
|
||||
(UINT64)-1LL, (UINT64)-1LL,
|
||||
((UINT64)Request->Req.LockControl.ProcessId << 32) | (UINT64)Request->Req.LockControl.Key);
|
||||
break;
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspFileSystemOpQuerySecurity(FSP_FILE_SYSTEM *FileSystem,
|
||||
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response)
|
||||
{
|
||||
|
@@ -117,6 +117,8 @@ static NTSTATUS FspFsvolCleanup(
|
||||
Request->Req.Cleanup.SetLastWriteTime = FileModified && !FileDesc->DidSetLastWriteTime;
|
||||
Request->Req.Cleanup.SetChangeTime = (FileModified || FileDesc->DidSetMetadata) &&
|
||||
!FileDesc->DidSetChangeTime;
|
||||
Request->Req.Cleanup.UnlockAll = FsvolDeviceExtension->VolumeParams.UserModeFileLocking &&
|
||||
FsRtlAreThereCurrentOrInProgressFileLocks(&FileNode->FileLock);
|
||||
|
||||
FspFileNodeAcquireExclusive(FileNode, Pgio);
|
||||
|
||||
@@ -128,6 +130,7 @@ static NTSTATUS FspFsvolCleanup(
|
||||
Request->Req.Cleanup.SetArchiveBit ||
|
||||
Request->Req.Cleanup.SetLastWriteTime ||
|
||||
Request->Req.Cleanup.SetChangeTime ||
|
||||
Request->Req.Cleanup.UnlockAll ||
|
||||
!FsvolDeviceExtension->VolumeParams.PostCleanupWhenModifiedOnly)
|
||||
/*
|
||||
* Note that it is still possible for this request to not be delivered,
|
||||
|
@@ -128,6 +128,7 @@ NTSTATUS DriverEntry(
|
||||
FspIopCompleteFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = FspFsvolFileSystemControlComplete;
|
||||
FspIopCompleteFunction[IRP_MJ_DEVICE_CONTROL] = FspFsvolDeviceControlComplete;
|
||||
FspIopCompleteFunction[IRP_MJ_SHUTDOWN] = FspFsvolShutdownComplete;
|
||||
FspFileNodeCompleteLockIrp = FspFsvolLockControlForward;
|
||||
FspIopCompleteFunction[IRP_MJ_LOCK_CONTROL] = FspFsvolLockControlComplete;
|
||||
FspIopCompleteFunction[IRP_MJ_CLEANUP] = FspFsvolCleanupComplete;
|
||||
FspIopCompleteFunction[IRP_MJ_QUERY_SECURITY] = FspFsvolQuerySecurityComplete;
|
||||
|
@@ -316,6 +316,7 @@ FSP_IOPREP_DISPATCH FspFsvolDirectoryControlPrepare;
|
||||
FSP_IOCMPL_DISPATCH FspFsvolDirectoryControlComplete;
|
||||
FSP_IOCMPL_DISPATCH FspFsvolFileSystemControlComplete;
|
||||
FSP_IOCMPL_DISPATCH FspFsvolFlushBuffersComplete;
|
||||
NTSTATUS FspFsvolLockControlForward(PVOID Context, PIRP Irp);
|
||||
FSP_IOCMPL_DISPATCH FspFsvolLockControlComplete;
|
||||
FSP_IOCMPL_DISPATCH FspFsvolQueryEaComplete;
|
||||
FSP_IOCMPL_DISPATCH FspFsvolQueryInformationComplete;
|
||||
@@ -1564,6 +1565,7 @@ extern CACHE_MANAGER_CALLBACKS FspCacheManagerCallbacks;
|
||||
extern FSP_IOPREP_DISPATCH *FspIopPrepareFunction[];
|
||||
extern FSP_IOCMPL_DISPATCH *FspIopCompleteFunction[];
|
||||
extern ERESOURCE FspDeviceGlobalResource;
|
||||
extern PCOMPLETE_LOCK_IRP_ROUTINE FspFileNodeCompleteLockIrp;
|
||||
extern WCHAR FspFileDescDirectoryPatternMatchAll[];
|
||||
extern const GUID FspMainFileOpenEcpGuid;
|
||||
extern ULONG FspProcessorCount;
|
||||
|
@@ -83,7 +83,6 @@ VOID FspFileNodeInvalidateStreamInfo(FSP_FILE_NODE *FileNode);
|
||||
VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode, ULONG Filter, ULONG Action,
|
||||
BOOLEAN InvalidateCaches);
|
||||
NTSTATUS FspFileNodeProcessLockIrp(FSP_FILE_NODE *FileNode, PIRP Irp);
|
||||
static NTSTATUS FspFileNodeCompleteLockIrp(PVOID Context, PIRP Irp);
|
||||
NTSTATUS FspFileDescCreate(FSP_FILE_DESC **PFileDesc);
|
||||
VOID FspFileDescDelete(FSP_FILE_DESC *FileDesc);
|
||||
NTSTATUS FspFileDescResetDirectory(FSP_FILE_DESC *FileDesc,
|
||||
@@ -149,7 +148,6 @@ VOID FspFileNodeOplockComplete(PVOID Context, PIRP Irp);
|
||||
// !#pragma alloc_text(PAGE, FspFileNodeInvalidateStreamInfo)
|
||||
#pragma alloc_text(PAGE, FspFileNodeNotifyChange)
|
||||
#pragma alloc_text(PAGE, FspFileNodeProcessLockIrp)
|
||||
#pragma alloc_text(PAGE, FspFileNodeCompleteLockIrp)
|
||||
#pragma alloc_text(PAGE, FspFileDescCreate)
|
||||
#pragma alloc_text(PAGE, FspFileDescDelete)
|
||||
#pragma alloc_text(PAGE, FspFileDescResetDirectory)
|
||||
@@ -2030,19 +2028,6 @@ NTSTATUS FspFileNodeProcessLockIrp(FSP_FILE_NODE *FileNode, PIRP Irp)
|
||||
return Result;
|
||||
}
|
||||
|
||||
static NTSTATUS FspFileNodeCompleteLockIrp(PVOID Context, PIRP Irp)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
NTSTATUS Result = Irp->IoStatus.Status;
|
||||
|
||||
DEBUGLOGIRP(Irp, Result);
|
||||
|
||||
FspIopCompleteIrp(Irp, Result);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
NTSTATUS FspFileDescCreate(FSP_FILE_DESC **PFileDesc)
|
||||
{
|
||||
PAGED_CODE();
|
||||
@@ -2379,6 +2364,7 @@ VOID FspFileNodeOplockComplete(PVOID Context, PIRP Irp)
|
||||
FspIopCompleteIrp(Irp, Irp->IoStatus.Status);
|
||||
}
|
||||
|
||||
PCOMPLETE_LOCK_IRP_ROUTINE FspFileNodeCompleteLockIrp;
|
||||
WCHAR FspFileDescDirectoryPatternMatchAll[] = L"*";
|
||||
|
||||
// {904862B4-EB3F-461E-ACB2-4DF2B3FC898B}
|
||||
|
@@ -22,12 +22,14 @@ static NTSTATUS FspFsvolLockControlRetry(
|
||||
BOOLEAN CanWait);
|
||||
static NTSTATUS FspFsvolLockControl(
|
||||
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspFsvolLockControlForward(PVOID Context, PIRP Irp);
|
||||
FSP_IOCMPL_DISPATCH FspFsvolLockControlComplete;
|
||||
FSP_DRIVER_DISPATCH FspLockControl;
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(PAGE, FspFsvolLockControlRetry)
|
||||
#pragma alloc_text(PAGE, FspFsvolLockControl)
|
||||
#pragma alloc_text(PAGE, FspFsvolLockControlForward)
|
||||
#pragma alloc_text(PAGE, FspFsvolLockControlComplete)
|
||||
#pragma alloc_text(PAGE, FspLockControl)
|
||||
#endif
|
||||
@@ -94,6 +96,57 @@ static NTSTATUS FspFsvolLockControl(
|
||||
return Result;
|
||||
}
|
||||
|
||||
NTSTATUS FspFsvolLockControlForward(PVOID Context, PIRP Irp)
|
||||
{
|
||||
/*
|
||||
* At this point the FSRTL package has processed the lock IRP.
|
||||
* Either complete the IRP or if we are supposed to forward to
|
||||
* user mode do so now.
|
||||
*/
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
PDEVICE_OBJECT FsvolDeviceObject = IrpSp->DeviceObject;
|
||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||
NTSTATUS Result = Irp->IoStatus.Status;
|
||||
|
||||
if (!NT_SUCCESS(Result) || !FsvolDeviceExtension->VolumeParams.UserModeFileLocking)
|
||||
goto complete;
|
||||
|
||||
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
|
||||
FSP_FSCTL_TRANSACT_REQ *Request;
|
||||
|
||||
ASSERT(FileNode == FileDesc->FileNode);
|
||||
|
||||
Result = FspIopCreateRequest(Irp, 0, 0, &Request);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto complete;
|
||||
|
||||
Request->Kind = FspFsctlTransactLockControlKind;
|
||||
Request->Req.LockControl.UserContext = FileNode->UserContext;
|
||||
Request->Req.LockControl.UserContext2 = FileDesc->UserContext2;
|
||||
Request->Req.LockControl.LockFunction = IrpSp->MinorFunction;
|
||||
Request->Req.LockControl.Offset = IrpSp->Parameters.LockControl.ByteOffset.QuadPart;
|
||||
Request->Req.LockControl.Length = IrpSp->Parameters.LockControl.Length->QuadPart;
|
||||
Request->Req.LockControl.Key = IrpSp->Parameters.LockControl.Key;
|
||||
Request->Req.LockControl.ProcessId = IoGetRequestorProcessId(Irp);
|
||||
Request->Req.LockControl.Exclusive = 0 != (IrpSp->Flags & SL_EXCLUSIVE_LOCK);
|
||||
Request->Req.LockControl.FailImmediately = 0 != (IrpSp->Flags & SL_FAIL_IMMEDIATELY);
|
||||
|
||||
if (!FspIoqPostIrp(FsvolDeviceExtension->Ioq, Irp, &Result))
|
||||
goto complete;
|
||||
|
||||
return Result;
|
||||
|
||||
complete:
|
||||
DEBUGLOGIRP(Irp, Result);
|
||||
FspIopCompleteIrp(Irp, Result);
|
||||
return Result;
|
||||
}
|
||||
|
||||
NTSTATUS FspFsvolLockControlComplete(
|
||||
PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
|
||||
{
|
||||
|
@@ -228,7 +228,6 @@ static NTSTATUS FspFsvolReadNonCached(
|
||||
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
|
||||
LARGE_INTEGER ReadOffset = IrpSp->Parameters.Read.ByteOffset;
|
||||
ULONG ReadLength = IrpSp->Parameters.Read.Length;
|
||||
ULONG ReadKey = IrpSp->Parameters.Read.Key;
|
||||
BOOLEAN PagingIo = BooleanFlagOn(Irp->Flags, IRP_PAGING_IO);
|
||||
FSP_FSCTL_TRANSACT_REQ *Request;
|
||||
BOOLEAN Success;
|
||||
@@ -321,7 +320,11 @@ static NTSTATUS FspFsvolReadNonCached(
|
||||
Request->Req.Read.UserContext2 = FileDesc->UserContext2;
|
||||
Request->Req.Read.Offset = ReadOffset.QuadPart;
|
||||
Request->Req.Read.Length = ReadLength;
|
||||
Request->Req.Read.Key = ReadKey;
|
||||
if (!PagingIo)
|
||||
{
|
||||
Request->Req.Read.Key = IrpSp->Parameters.Read.Key;
|
||||
Request->Req.Read.ProcessId = IoGetRequestorProcessId(Irp);
|
||||
}
|
||||
|
||||
FspFileNodeSetOwner(FileNode, Full, Request);
|
||||
FspIopRequestContext(Request, RequestIrp) = Irp;
|
||||
|
@@ -289,7 +289,6 @@ static NTSTATUS FspFsvolWriteNonCached(
|
||||
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
|
||||
LARGE_INTEGER WriteOffset = IrpSp->Parameters.Write.ByteOffset;
|
||||
ULONG WriteLength = IrpSp->Parameters.Write.Length;
|
||||
ULONG WriteKey = IrpSp->Parameters.Write.Key;
|
||||
BOOLEAN WriteToEndOfFile =
|
||||
FILE_WRITE_TO_END_OF_FILE == WriteOffset.LowPart && -1L == WriteOffset.HighPart;
|
||||
BOOLEAN PagingIo = BooleanFlagOn(Irp->Flags, IRP_PAGING_IO);
|
||||
@@ -390,8 +389,13 @@ static NTSTATUS FspFsvolWriteNonCached(
|
||||
Request->Req.Write.UserContext2 = FileDesc->UserContext2;
|
||||
Request->Req.Write.Offset = WriteOffset.QuadPart;
|
||||
Request->Req.Write.Length = WriteLength;
|
||||
Request->Req.Write.Key = WriteKey;
|
||||
Request->Req.Write.ConstrainedIo = !!PagingIo;
|
||||
if (!PagingIo)
|
||||
{
|
||||
Request->Req.Write.Key = IrpSp->Parameters.Write.Key;
|
||||
Request->Req.Write.ProcessId = IoGetRequestorProcessId(Irp);
|
||||
}
|
||||
else
|
||||
Request->Req.Write.ConstrainedIo = TRUE;
|
||||
|
||||
FspFileNodeSetOwner(FileNode, Full, Request);
|
||||
FspIopRequestContext(Request, RequestIrp) = Irp;
|
||||
|
Reference in New Issue
Block a user