mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-22 16:33:02 -05:00
sys: oplock: perform stream oplock checks
sys: rename: fix some rename issues
This commit is contained in:
parent
8750451e10
commit
e4de0f0513
107
src/sys/create.c
107
src/sys/create.c
@ -521,6 +521,10 @@ static NTSTATUS FspFsvolCreateNoLock(
|
|||||||
FspFileNameSuffix(&FileNode->FileName, &FileNode->FileName, &Suffix);
|
FspFileNameSuffix(&FileNode->FileName, &FileNode->FileName, &Suffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* zero Irp->IoStatus, because we now use it to maintain state in FspFsvolCreateComplete */
|
||||||
|
Irp->IoStatus.Status = 0;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
|
||||||
return FSP_STATUS_IOQ_POST;
|
return FSP_STATUS_IOQ_POST;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -640,6 +644,7 @@ NTSTATUS FspFsvolCreateComplete(
|
|||||||
FSP_FILE_DESC *FileDesc = FspIopRequestContext(Request, RequestFileDesc);
|
FSP_FILE_DESC *FileDesc = FspIopRequestContext(Request, RequestFileDesc);
|
||||||
FSP_FILE_NODE *FileNode = FileDesc->FileNode;
|
FSP_FILE_NODE *FileNode = FileDesc->FileNode;
|
||||||
FSP_FILE_NODE *OpenedFileNode;
|
FSP_FILE_NODE *OpenedFileNode;
|
||||||
|
ULONG SharingViolationReason;
|
||||||
UNICODE_STRING NormalizedName;
|
UNICODE_STRING NormalizedName;
|
||||||
PREPARSE_DATA_BUFFER ReparseData;
|
PREPARSE_DATA_BUFFER ReparseData;
|
||||||
UNICODE_STRING ReparseTargetPrefix0, ReparseTargetPrefix1, ReparseTargetPath;
|
UNICODE_STRING ReparseTargetPrefix0, ReparseTargetPrefix1, ReparseTargetPath;
|
||||||
@ -838,21 +843,38 @@ NTSTATUS FspFsvolCreateComplete(
|
|||||||
/* open the FileNode */
|
/* open the FileNode */
|
||||||
Result = FspFileNodeOpen(FileNode, FileObject,
|
Result = FspFileNodeOpen(FileNode, FileObject,
|
||||||
Response->Rsp.Create.Opened.GrantedAccess, IrpSp->Parameters.Create.ShareAccess,
|
Response->Rsp.Create.Opened.GrantedAccess, IrpSp->Parameters.Create.ShareAccess,
|
||||||
&OpenedFileNode);
|
&OpenedFileNode, &SharingViolationReason);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
{
|
{
|
||||||
if (STATUS_SHARING_VIOLATION == Result)
|
if (STATUS_SHARING_VIOLATION == Result)
|
||||||
{
|
{
|
||||||
ASSERT(0 != OpenedFileNode);
|
ASSERT(0 != OpenedFileNode);
|
||||||
|
|
||||||
FspIopSetIrpResponse(Irp, Response);
|
if (STATUS_SHARING_VIOLATION != Irp->IoStatus.Status)
|
||||||
FspIopRequestContext(Request, FspIopRequestExtraContext) = OpenedFileNode;
|
{
|
||||||
|
ASSERT(0 == Irp->IoStatus.Information ||
|
||||||
|
FILE_OPBATCH_BREAK_UNDERWAY == Irp->IoStatus.Information);
|
||||||
|
|
||||||
Result = FspFsvolCreateSharingViolationOplock(
|
FspIopSetIrpResponse(Irp, Response);
|
||||||
FsvolDeviceObject, Irp, IrpSp, FALSE);
|
FspIopRequestContext(Request, FspIopRequestExtraContext) = OpenedFileNode;
|
||||||
if (STATUS_PENDING == Result)
|
|
||||||
FSP_RETURN();
|
/* HACK: We have run out of Contexts. Store the sharing violation reason in the IRP. */
|
||||||
|
Irp->IoStatus.Status = STATUS_SHARING_VIOLATION;
|
||||||
|
Irp->IoStatus.Information = SharingViolationReason;
|
||||||
|
|
||||||
|
Result = FspFsvolCreateSharingViolationOplock(
|
||||||
|
FsvolDeviceObject, Irp, IrpSp, FALSE);
|
||||||
|
if (STATUS_PENDING == Result)
|
||||||
|
FSP_RETURN();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FspFileNodeClose(OpenedFileNode, 0, TRUE);
|
||||||
|
FspFileNodeDereference(OpenedFileNode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
ASSERT(0 == OpenedFileNode);
|
||||||
|
|
||||||
/* unable to open the FileNode; post a Close request */
|
/* unable to open the FileNode; post a Close request */
|
||||||
FspFsvolCreatePostClose(FileDesc);
|
FspFsvolCreatePostClose(FileDesc);
|
||||||
@ -1245,18 +1267,22 @@ static NTSTATUS FspFsvolCreateSharingViolationOplock(
|
|||||||
* try to break both Batch and Handle oplocks and return the appropriate status
|
* try to break both Batch and Handle oplocks and return the appropriate status
|
||||||
* code.
|
* code.
|
||||||
*
|
*
|
||||||
* We acquire the FileNode shared so allow oplock breaks to happen concurrently.
|
* We acquire the FileNode shared to allow oplock breaks to happen concurrently.
|
||||||
* See https://www.osronline.com/showthread.cfm?link=248984
|
* See https://www.osronline.com/showthread.cfm?link=248984
|
||||||
*/
|
*/
|
||||||
|
|
||||||
FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp);
|
FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp);
|
||||||
FSP_FSCTL_TRANSACT_RSP *Response;
|
FSP_FSCTL_TRANSACT_RSP *Response;
|
||||||
FSP_FILE_NODE *ExtraFileNode = FspIopRequestContext(Request, FspIopRequestExtraContext);
|
FSP_FILE_NODE *ExtraFileNode = FspIopRequestContext(Request, FspIopRequestExtraContext);
|
||||||
BOOLEAN OpbatchBreakUnderway = FALSE;
|
ULONG SharingViolationReason = (ULONG)Irp->IoStatus.Information;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
BOOLEAN Success;
|
BOOLEAN Success;
|
||||||
|
|
||||||
ASSERT(FspFsctlTransactCreateKind == Request->Kind);
|
ASSERT(FspFsctlTransactCreateKind == Request->Kind);
|
||||||
|
ASSERT(
|
||||||
|
FspFileNodeSharingViolationGeneral == SharingViolationReason ||
|
||||||
|
FspFileNodeSharingViolationMainFile == SharingViolationReason ||
|
||||||
|
FspFileNodeSharingViolationStream == SharingViolationReason);
|
||||||
|
|
||||||
Success = DEBUGTEST(90) &&
|
Success = DEBUGTEST(90) &&
|
||||||
FspFileNodeTryAcquireSharedF(ExtraFileNode, FspFileNodeAcquireMain, CanWait);
|
FspFileNodeTryAcquireSharedF(ExtraFileNode, FspFileNodeAcquireMain, CanWait);
|
||||||
@ -1271,7 +1297,9 @@ static NTSTATUS FspFsvolCreateSharingViolationOplock(
|
|||||||
* worker thread to break the oplocks.
|
* worker thread to break the oplocks.
|
||||||
*/
|
*/
|
||||||
Success = DEBUGTEST(90) &&
|
Success = DEBUGTEST(90) &&
|
||||||
!FsRtlCurrentBatchOplock(FspFileNodeAddrOfOplock(ExtraFileNode)) &&
|
!(FspFileNodeSharingViolationMainFile == SharingViolationReason) &&
|
||||||
|
!(FspFileNodeSharingViolationStream == SharingViolationReason) &&
|
||||||
|
!(FsRtlCurrentBatchOplock(FspFileNodeAddrOfOplock(ExtraFileNode))) &&
|
||||||
!(!FlagOn(IrpSp->Parameters.Create.Options, FILE_COMPLETE_IF_OPLOCKED) &&
|
!(!FlagOn(IrpSp->Parameters.Create.Options, FILE_COMPLETE_IF_OPLOCKED) &&
|
||||||
FsRtlCurrentOplockH(FspFileNodeAddrOfOplock(ExtraFileNode)));
|
FsRtlCurrentOplockH(FspFileNodeAddrOfOplock(ExtraFileNode)));
|
||||||
|
|
||||||
@ -1286,16 +1314,55 @@ static NTSTATUS FspFsvolCreateSharingViolationOplock(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
|
||||||
|
Result = STATUS_SHARING_VIOLATION;
|
||||||
|
if (FspFileNodeSharingViolationMainFile == SharingViolationReason)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* If a SUPERSEDE, OVERWRITE or OVERWRITE_IF operation is performed
|
||||||
|
* on an alternate data stream and FILE_SHARE_DELETE is not specified
|
||||||
|
* and there is a Batch or Filter oplock on the primary data stream,
|
||||||
|
* request a break of the Batch or Filter oplock on the primary data
|
||||||
|
* stream.
|
||||||
|
*/
|
||||||
|
|
||||||
|
FSP_FILE_DESC *FileDesc = FspIopRequestContext(Request, RequestFileDesc);
|
||||||
|
FSP_FILE_NODE *FileNode = FileDesc->FileNode;
|
||||||
|
|
||||||
|
/* break Batch oplocks on the main file and this stream */
|
||||||
|
Result = FspFileNodeCheckBatchOplocksOnAllStreams(FsvolDeviceObject, Irp,
|
||||||
|
ExtraFileNode, &FileNode->FileName);
|
||||||
|
if (STATUS_SUCCESS != Result)
|
||||||
|
Result = STATUS_SHARING_VIOLATION;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (FspFileNodeSharingViolationStream == SharingViolationReason)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* If a SUPERSEDE, OVERWRITE or OVERWRITE_IF operation is performed
|
||||||
|
* on the primary data stream and DELETE access has been requested
|
||||||
|
* and there are Batch or Filter oplocks on any alternate data stream,
|
||||||
|
* request a break of the Batch or Filter oplocks on all alternate data
|
||||||
|
* streams that have them.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* break Batch oplocks on the main file and all our streams */
|
||||||
|
Result = FspFileNodeCheckBatchOplocksOnAllStreams(FsvolDeviceObject, Irp,
|
||||||
|
ExtraFileNode, 0);
|
||||||
|
if (STATUS_SUCCESS != Result)
|
||||||
|
Result = STATUS_SHARING_VIOLATION;
|
||||||
|
}
|
||||||
|
else
|
||||||
if (FsRtlCurrentBatchOplock(FspFileNodeAddrOfOplock(ExtraFileNode)))
|
if (FsRtlCurrentBatchOplock(FspFileNodeAddrOfOplock(ExtraFileNode)))
|
||||||
{
|
{
|
||||||
/* wait for Batch oplock break to complete */
|
/* wait for Batch oplock break to complete */
|
||||||
Result = FspCheckOplock(FspFileNodeAddrOfOplock(ExtraFileNode), Irp,
|
Result = FspCheckOplock(FspFileNodeAddrOfOplock(ExtraFileNode), Irp,
|
||||||
0, 0, 0);
|
0, 0, 0);
|
||||||
if (STATUS_SUCCESS == Result)
|
if (STATUS_SUCCESS != Result)
|
||||||
OpbatchBreakUnderway = TRUE;
|
Result = STATUS_SHARING_VIOLATION;
|
||||||
|
else
|
||||||
/* if a Batch oplock is broken, we still return STATUS_SHARING_VIOLATION */
|
Irp->IoStatus.Information = FILE_OPBATCH_BREAK_UNDERWAY;
|
||||||
Result = STATUS_SHARING_VIOLATION;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (!FlagOn(IrpSp->Parameters.Create.Options, FILE_COMPLETE_IF_OPLOCKED) &&
|
if (!FlagOn(IrpSp->Parameters.Create.Options, FILE_COMPLETE_IF_OPLOCKED) &&
|
||||||
@ -1305,11 +1372,9 @@ static NTSTATUS FspFsvolCreateSharingViolationOplock(
|
|||||||
Result = FspOplockBreakH(FspFileNodeAddrOfOplock(ExtraFileNode), Irp,
|
Result = FspOplockBreakH(FspFileNodeAddrOfOplock(ExtraFileNode), Irp,
|
||||||
0, 0, 0, 0);
|
0, 0, 0, 0);
|
||||||
ASSERT(STATUS_OPLOCK_BREAK_IN_PROGRESS != Result);
|
ASSERT(STATUS_OPLOCK_BREAK_IN_PROGRESS != Result);
|
||||||
|
if (STATUS_SUCCESS != Result)
|
||||||
/* if a Handle oplock is broken, we can actually retry the sharing check */
|
Result = STATUS_SHARING_VIOLATION;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
Result = STATUS_SHARING_VIOLATION;
|
|
||||||
|
|
||||||
FspFileNodeRelease(ExtraFileNode, Main);
|
FspFileNodeRelease(ExtraFileNode, Main);
|
||||||
|
|
||||||
@ -1324,9 +1389,7 @@ static NTSTATUS FspFsvolCreateSharingViolationOplock(
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
Response->IoStatus.Status = (UINT32)Result;
|
Response->IoStatus.Status = (UINT32)Result;
|
||||||
Response->IoStatus.Information =
|
Response->IoStatus.Information = (UINT32)Irp->IoStatus.Information;
|
||||||
STATUS_SHARING_VIOLATION == Result && OpbatchBreakUnderway ?
|
|
||||||
FILE_OPBATCH_BREAK_UNDERWAY : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FspIopRetryCompleteIrp(Irp, Response, &Result);
|
FspIopRetryCompleteIrp(Irp, Response, &Result);
|
||||||
|
@ -634,9 +634,9 @@ PVOID FspFsvolDeviceEnumerateContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE
|
|||||||
|
|
||||||
if (0 != Result &&
|
if (0 != Result &&
|
||||||
FspFileNameIsPrefix(FileName, Result->FileName, CaseInsensitive, 0) &&
|
FspFileNameIsPrefix(FileName, Result->FileName, CaseInsensitive, 0) &&
|
||||||
FileName->Length < Result->FileName->Length &&
|
(FileName->Length == Result->FileName->Length ||
|
||||||
(L'\\' == Result->FileName->Buffer[FileName->Length / sizeof(WCHAR)] ||
|
(L'\\' == Result->FileName->Buffer[FileName->Length / sizeof(WCHAR)] ||
|
||||||
L':' == Result->FileName->Buffer[FileName->Length / sizeof(WCHAR)]))
|
L':' == Result->FileName->Buffer[FileName->Length / sizeof(WCHAR)])))
|
||||||
return Result->Context;
|
return Result->Context;
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -976,6 +976,12 @@ enum
|
|||||||
FspFileNodeFileKind = 'BZ',
|
FspFileNodeFileKind = 'BZ',
|
||||||
};
|
};
|
||||||
enum
|
enum
|
||||||
|
{
|
||||||
|
FspFileNodeSharingViolationGeneral = 'G',
|
||||||
|
FspFileNodeSharingViolationMainFile = 'M',
|
||||||
|
FspFileNodeSharingViolationStream = 'S',
|
||||||
|
};
|
||||||
|
enum
|
||||||
{
|
{
|
||||||
FspFileNodeAcquireMain = 1,
|
FspFileNodeAcquireMain = 1,
|
||||||
FspFileNodeAcquirePgio = 2,
|
FspFileNodeAcquirePgio = 2,
|
||||||
@ -1108,7 +1114,8 @@ VOID FspFileNodeReleaseForeign(FSP_FILE_NODE *FileNode)
|
|||||||
ExReleaseResourceLite(FileNode->Header.Resource);
|
ExReleaseResourceLite(FileNode->Header.Resource);
|
||||||
}
|
}
|
||||||
NTSTATUS FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
NTSTATUS FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
||||||
UINT32 GrantedAccess, UINT32 ShareAccess, FSP_FILE_NODE **POpenedFileNode);
|
UINT32 GrantedAccess, UINT32 ShareAccess,
|
||||||
|
FSP_FILE_NODE **POpenedFileNode, PULONG PSharingViolationReason);
|
||||||
VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
||||||
PBOOLEAN PDeletePending);
|
PBOOLEAN PDeletePending);
|
||||||
VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject);
|
VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject);
|
||||||
@ -1117,6 +1124,11 @@ VOID FspFileNodeClose(FSP_FILE_NODE *FileNode,
|
|||||||
BOOLEAN HandleCleanup); /* TRUE to decrement handle count */
|
BOOLEAN HandleCleanup); /* TRUE to decrement handle count */
|
||||||
NTSTATUS FspFileNodeFlushAndPurgeCache(FSP_FILE_NODE *FileNode,
|
NTSTATUS FspFileNodeFlushAndPurgeCache(FSP_FILE_NODE *FileNode,
|
||||||
UINT64 FlushOffset64, ULONG FlushLength, BOOLEAN FlushAndPurge);
|
UINT64 FlushOffset64, ULONG FlushLength, BOOLEAN FlushAndPurge);
|
||||||
|
NTSTATUS FspFileNodeCheckBatchOplocksOnAllStreams(
|
||||||
|
PDEVICE_OBJECT FsvolDeviceObject,
|
||||||
|
PIRP OplockIrp,
|
||||||
|
FSP_FILE_NODE *FileNode,
|
||||||
|
PUNICODE_STRING StreamFileName);
|
||||||
BOOLEAN FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp,
|
BOOLEAN FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp,
|
||||||
FSP_FILE_NODE *FileNode, PUNICODE_STRING FileName);
|
FSP_FILE_NODE *FileNode, PUNICODE_STRING FileName);
|
||||||
VOID FspFileNodeRename(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName);
|
VOID FspFileNodeRename(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName);
|
||||||
|
165
src/sys/file.c
165
src/sys/file.c
@ -32,7 +32,8 @@ VOID FspFileNodeSetOwnerF(FSP_FILE_NODE *FileNode, ULONG Flags, PVOID Owner);
|
|||||||
VOID FspFileNodeReleaseF(FSP_FILE_NODE *FileNode, ULONG Flags);
|
VOID FspFileNodeReleaseF(FSP_FILE_NODE *FileNode, ULONG Flags);
|
||||||
VOID FspFileNodeReleaseOwnerF(FSP_FILE_NODE *FileNode, ULONG Flags, PVOID Owner);
|
VOID FspFileNodeReleaseOwnerF(FSP_FILE_NODE *FileNode, ULONG Flags, PVOID Owner);
|
||||||
NTSTATUS FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
NTSTATUS FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
||||||
UINT32 GrantedAccess, UINT32 ShareAccess, FSP_FILE_NODE **POpenedFileNode);
|
UINT32 GrantedAccess, UINT32 ShareAccess,
|
||||||
|
FSP_FILE_NODE **POpenedFileNode, PULONG PSharingViolationReason);
|
||||||
VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
||||||
PBOOLEAN PDeletePending);
|
PBOOLEAN PDeletePending);
|
||||||
VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject);
|
VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject);
|
||||||
@ -41,6 +42,11 @@ VOID FspFileNodeClose(FSP_FILE_NODE *FileNode,
|
|||||||
BOOLEAN HandleCleanup); /* TRUE to decrement handle count */
|
BOOLEAN HandleCleanup); /* TRUE to decrement handle count */
|
||||||
NTSTATUS FspFileNodeFlushAndPurgeCache(FSP_FILE_NODE *FileNode,
|
NTSTATUS FspFileNodeFlushAndPurgeCache(FSP_FILE_NODE *FileNode,
|
||||||
UINT64 FlushOffset64, ULONG FlushLength, BOOLEAN FlushAndPurge);
|
UINT64 FlushOffset64, ULONG FlushLength, BOOLEAN FlushAndPurge);
|
||||||
|
NTSTATUS FspFileNodeCheckBatchOplocksOnAllStreams(
|
||||||
|
PDEVICE_OBJECT FsvolDeviceObject,
|
||||||
|
PIRP OplockIrp,
|
||||||
|
FSP_FILE_NODE *FileNode,
|
||||||
|
PUNICODE_STRING StreamFileName);
|
||||||
BOOLEAN FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp,
|
BOOLEAN FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp,
|
||||||
FSP_FILE_NODE *FileNode, PUNICODE_STRING FileName);
|
FSP_FILE_NODE *FileNode, PUNICODE_STRING FileName);
|
||||||
VOID FspFileNodeRename(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName);
|
VOID FspFileNodeRename(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName);
|
||||||
@ -103,6 +109,7 @@ NTSTATUS FspMainFileClose(
|
|||||||
#pragma alloc_text(PAGE, FspFileNodeCleanupComplete)
|
#pragma alloc_text(PAGE, FspFileNodeCleanupComplete)
|
||||||
#pragma alloc_text(PAGE, FspFileNodeClose)
|
#pragma alloc_text(PAGE, FspFileNodeClose)
|
||||||
#pragma alloc_text(PAGE, FspFileNodeFlushAndPurgeCache)
|
#pragma alloc_text(PAGE, FspFileNodeFlushAndPurgeCache)
|
||||||
|
#pragma alloc_text(PAGE, FspFileNodeCheckBatchOplocksOnAllStreams)
|
||||||
#pragma alloc_text(PAGE, FspFileNodeRenameCheck)
|
#pragma alloc_text(PAGE, FspFileNodeRenameCheck)
|
||||||
#pragma alloc_text(PAGE, FspFileNodeRename)
|
#pragma alloc_text(PAGE, FspFileNodeRename)
|
||||||
#pragma alloc_text(PAGE, FspFileNodeGetFileInfo)
|
#pragma alloc_text(PAGE, FspFileNodeGetFileInfo)
|
||||||
@ -449,7 +456,8 @@ VOID FspFileNodeReleaseOwnerF(FSP_FILE_NODE *FileNode, ULONG Flags, PVOID Owner)
|
|||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
NTSTATUS FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
||||||
UINT32 GrantedAccess, UINT32 ShareAccess, FSP_FILE_NODE **POpenedFileNode)
|
UINT32 GrantedAccess, UINT32 ShareAccess,
|
||||||
|
FSP_FILE_NODE **POpenedFileNode, PULONG PSharingViolationReason)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Attempt to insert our FileNode into the volume device's generic table.
|
* Attempt to insert our FileNode into the volume device's generic table.
|
||||||
@ -466,6 +474,8 @@ NTSTATUS FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
|||||||
BOOLEAN Inserted, DeletePending;
|
BOOLEAN Inserted, DeletePending;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
*PSharingViolationReason = FspFileNodeSharingViolationGeneral;
|
||||||
|
|
||||||
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
|
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -494,6 +504,7 @@ NTSTATUS FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
|||||||
FILE_EXECUTE | FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA | DELETE))
|
FILE_EXECUTE | FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA | DELETE))
|
||||||
{
|
{
|
||||||
OpenedFileNode = FileNode->MainFileNode;
|
OpenedFileNode = FileNode->MainFileNode;
|
||||||
|
*PSharingViolationReason = FspFileNodeSharingViolationMainFile;
|
||||||
Result = STATUS_SHARING_VIOLATION;
|
Result = STATUS_SHARING_VIOLATION;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
@ -544,6 +555,7 @@ NTSTATUS FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
|||||||
|
|
||||||
if (FlagOn(GrantedAccess, DELETE))
|
if (FlagOn(GrantedAccess, DELETE))
|
||||||
{
|
{
|
||||||
|
*PSharingViolationReason = FspFileNodeSharingViolationStream;
|
||||||
Result = STATUS_SHARING_VIOLATION;
|
Result = STATUS_SHARING_VIOLATION;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
@ -834,6 +846,149 @@ NTSTATUS FspFileNodeFlushAndPurgeCache(FSP_FILE_NODE *FileNode,
|
|||||||
return IoStatus.Status;
|
return IoStatus.Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS FspFileNodeCheckBatchOplocksOnAllStreams(
|
||||||
|
PDEVICE_OBJECT FsvolDeviceObject,
|
||||||
|
PIRP OplockIrp,
|
||||||
|
FSP_FILE_NODE *FileNode,
|
||||||
|
PUNICODE_STRING StreamFileName)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Called during Create processing. The device rename resource has been acquired shared.
|
||||||
|
* No concurrent renames are allowed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
ASSERT(0 == FileNode->MainFileNode);
|
||||||
|
|
||||||
|
FSP_FILE_NODE *DescendantFileNode;
|
||||||
|
FSP_FILE_NODE *DescendantFileNodeArray[16], **DescendantFileNodes;
|
||||||
|
ULONG DescendantFileNodeCount, DescendantFileNodeIndex;
|
||||||
|
FSP_DEVICE_CONTEXT_BY_NAME_TABLE_RESTART_KEY RestartKey;
|
||||||
|
USHORT FileNameLength = FileNode->FileName.Length;
|
||||||
|
BOOLEAN CaseInsensitive = !FspFsvolDeviceExtension(FsvolDeviceObject)->
|
||||||
|
VolumeParams.CaseSensitiveSearch;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
DescendantFileNodes = DescendantFileNodeArray;
|
||||||
|
DescendantFileNodeCount = 0;
|
||||||
|
|
||||||
|
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
|
||||||
|
|
||||||
|
/* count descendant file nodes and try to gather them in a local array if possible */
|
||||||
|
memset(&RestartKey, 0, sizeof RestartKey);
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
DescendantFileNode = FspFsvolDeviceEnumerateContextByName(FsvolDeviceObject,
|
||||||
|
&FileNode->FileName, FALSE, &RestartKey);
|
||||||
|
if (0 == DescendantFileNode)
|
||||||
|
break;
|
||||||
|
if (DescendantFileNode->FileName.Length > FileNameLength &&
|
||||||
|
L'\\' == DescendantFileNode->FileName.Buffer[FileNameLength / sizeof(WCHAR)])
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (1 >= DescendantFileNode->HandleCount)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (0 != StreamFileName)
|
||||||
|
{
|
||||||
|
if (DescendantFileNode != FileNode &&
|
||||||
|
0 != FspFileNameCompare(&DescendantFileNode->FileName, StreamFileName,
|
||||||
|
CaseInsensitive, 0))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* keep a reference to the FileNode in case it goes away in later processing */
|
||||||
|
FspFileNodeReference(DescendantFileNode);
|
||||||
|
|
||||||
|
if (ARRAYSIZE(DescendantFileNodeArray) > DescendantFileNodeCount)
|
||||||
|
DescendantFileNodes[DescendantFileNodeCount] = DescendantFileNode;
|
||||||
|
DescendantFileNodeCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT(0 != StreamFileName || DescendantFileNodeCount <= 2);
|
||||||
|
|
||||||
|
/* if the local array is out of space, gather descendant file nodes in the pool */
|
||||||
|
if (ARRAYSIZE(DescendantFileNodeArray) < DescendantFileNodeCount)
|
||||||
|
{
|
||||||
|
ASSERT(0 == StreamFileName);
|
||||||
|
|
||||||
|
DescendantFileNodes = FspAllocMustSucceed(DescendantFileNodeCount * sizeof(FSP_FILE_NODE *));
|
||||||
|
DescendantFileNodeIndex = 0;
|
||||||
|
memset(&RestartKey, 0, sizeof RestartKey);
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
DescendantFileNode = FspFsvolDeviceEnumerateContextByName(FsvolDeviceObject,
|
||||||
|
&FileNode->FileName, FALSE, &RestartKey);
|
||||||
|
if (0 == DescendantFileNode)
|
||||||
|
break;
|
||||||
|
if (DescendantFileNode->FileName.Length > FileNameLength &&
|
||||||
|
L'\\' == DescendantFileNode->FileName.Buffer[FileNameLength / sizeof(WCHAR)])
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (1 >= DescendantFileNode->HandleCount)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
DescendantFileNodes[DescendantFileNodeIndex] = DescendantFileNode;
|
||||||
|
DescendantFileNodeIndex++;
|
||||||
|
ASSERT(DescendantFileNodeCount >= DescendantFileNodeIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT(DescendantFileNodeCount == DescendantFileNodeIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
FspFsvolDeviceUnlockContextTable(FsvolDeviceObject);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* At this point all descendant FileNode's are enumerated and referenced.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* break any Batch or Handle oplocks on descendants */
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
for (
|
||||||
|
DescendantFileNodeIndex = 0;
|
||||||
|
DescendantFileNodeCount > DescendantFileNodeIndex;
|
||||||
|
DescendantFileNodeIndex++)
|
||||||
|
{
|
||||||
|
DescendantFileNode = DescendantFileNodes[DescendantFileNodeIndex];
|
||||||
|
|
||||||
|
if (FsRtlCurrentBatchOplock(FspFileNodeAddrOfOplock(DescendantFileNode)))
|
||||||
|
{
|
||||||
|
NTSTATUS Result0 = FspCheckOplock(FspFileNodeAddrOfOplock(DescendantFileNode), OplockIrp,
|
||||||
|
0, 0, 0);
|
||||||
|
if (STATUS_SUCCESS != Result0)
|
||||||
|
Result = STATUS_SHARING_VIOLATION;
|
||||||
|
else
|
||||||
|
OplockIrp->IoStatus.Information = FILE_OPBATCH_BREAK_UNDERWAY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (FsRtlCurrentOplockH(FspFileNodeAddrOfOplock(DescendantFileNode)))
|
||||||
|
{
|
||||||
|
NTSTATUS Result0 = FspOplockBreakH(FspFileNodeAddrOfOplock(DescendantFileNode), OplockIrp,
|
||||||
|
0, 0, 0, 0);
|
||||||
|
ASSERT(STATUS_OPLOCK_BREAK_IN_PROGRESS != Result0);
|
||||||
|
if (STATUS_SUCCESS != Result0)
|
||||||
|
Result = STATUS_SHARING_VIOLATION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* dereference all FileNode's referenced during initial enumeration */
|
||||||
|
for (
|
||||||
|
DescendantFileNodeIndex = 0;
|
||||||
|
DescendantFileNodeCount > DescendantFileNodeIndex;
|
||||||
|
DescendantFileNodeIndex++)
|
||||||
|
{
|
||||||
|
DescendantFileNode = DescendantFileNodes[DescendantFileNodeIndex];
|
||||||
|
|
||||||
|
FspFileNodeDereference(DescendantFileNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DescendantFileNodeArray != DescendantFileNodes)
|
||||||
|
FspFree(DescendantFileNodes);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
BOOLEAN FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp,
|
BOOLEAN FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp,
|
||||||
FSP_FILE_NODE *FileNode, PUNICODE_STRING FileName)
|
FSP_FILE_NODE *FileNode, PUNICODE_STRING FileName)
|
||||||
{
|
{
|
||||||
@ -952,7 +1107,7 @@ BOOLEAN FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* break any batch oplocks on descendants */
|
/* break any Batch or Handle oplocks on descendants */
|
||||||
for (
|
for (
|
||||||
DescendantFileNodeIndex = 0;
|
DescendantFileNodeIndex = 0;
|
||||||
DescendantFileNodeCount > DescendantFileNodeIndex;
|
DescendantFileNodeCount > DescendantFileNodeIndex;
|
||||||
@ -963,7 +1118,9 @@ BOOLEAN FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp,
|
|||||||
DescendantFileNode = (PVOID)((UINT_PTR)DescendantFileNode & ~1);
|
DescendantFileNode = (PVOID)((UINT_PTR)DescendantFileNode & ~1);
|
||||||
|
|
||||||
if (HasOpenHandles)
|
if (HasOpenHandles)
|
||||||
FspCheckOplock(FspFileNodeAddrOfOplock(DescendantFileNode), OplockIrp, 0, 0, 0);
|
if (FsRtlCurrentBatchOplock(FspFileNodeAddrOfOplock(DescendantFileNode)) ||
|
||||||
|
FsRtlCurrentOplockH(FspFileNodeAddrOfOplock(DescendantFileNode)))
|
||||||
|
FspCheckOplock(FspFileNodeAddrOfOplock(DescendantFileNode), OplockIrp, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
|
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
|
||||||
|
@ -1283,7 +1283,8 @@ retry:
|
|||||||
*/
|
*/
|
||||||
Result = STATUS_SUCCESS;
|
Result = STATUS_SUCCESS;
|
||||||
if (!FspFileNodeRenameCheck(FsvolDeviceObject, Irp, FileNode, &FileNode->FileName) ||
|
if (!FspFileNodeRenameCheck(FsvolDeviceObject, Irp, FileNode, &FileNode->FileName) ||
|
||||||
!FspFileNodeRenameCheck(FsvolDeviceObject, Irp, 0, &NewFileName))
|
(0 != FspFileNameCompare(&FileNode->FileName, &NewFileName, !FileDesc->CaseSensitive, 0) &&
|
||||||
|
!FspFileNodeRenameCheck(FsvolDeviceObject, Irp, 0, &NewFileName)))
|
||||||
Result = STATUS_ACCESS_DENIED;
|
Result = STATUS_ACCESS_DENIED;
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
return Result;
|
return Result;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user