mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-23 08:53:01 -05:00
sys: rename: oplock refactoring
This commit is contained in:
parent
8f10ba4fc9
commit
ba78fbb956
@ -1123,8 +1123,9 @@ NTSTATUS FspFileNodeCheckBatchOplocksOnAllStreams(
|
|||||||
FSP_FILE_NODE *FileNode,
|
FSP_FILE_NODE *FileNode,
|
||||||
ULONG AcquireFlags,
|
ULONG AcquireFlags,
|
||||||
PUNICODE_STRING StreamFileName);
|
PUNICODE_STRING StreamFileName);
|
||||||
BOOLEAN FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp,
|
NTSTATUS FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp,
|
||||||
FSP_FILE_NODE *FileNode, PUNICODE_STRING FileName);
|
FSP_FILE_NODE *FileNode, ULONG AcquireFlags,
|
||||||
|
PUNICODE_STRING FileName, BOOLEAN CheckingOldName);
|
||||||
VOID FspFileNodeRename(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName);
|
VOID FspFileNodeRename(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName);
|
||||||
VOID FspFileNodeGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo);
|
VOID FspFileNodeGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo);
|
||||||
BOOLEAN FspFileNodeTryGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo);
|
BOOLEAN FspFileNodeTryGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo);
|
||||||
|
159
src/sys/file.c
Normal file → Executable file
159
src/sys/file.c
Normal file → Executable file
@ -48,8 +48,9 @@ NTSTATUS FspFileNodeCheckBatchOplocksOnAllStreams(
|
|||||||
FSP_FILE_NODE *FileNode,
|
FSP_FILE_NODE *FileNode,
|
||||||
ULONG AcquireFlags,
|
ULONG AcquireFlags,
|
||||||
PUNICODE_STRING StreamFileName);
|
PUNICODE_STRING StreamFileName);
|
||||||
BOOLEAN FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp,
|
NTSTATUS FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp,
|
||||||
FSP_FILE_NODE *FileNode, PUNICODE_STRING FileName);
|
FSP_FILE_NODE *FileNode, ULONG AcquireFlags,
|
||||||
|
PUNICODE_STRING FileName, BOOLEAN CheckingOldName);
|
||||||
VOID FspFileNodeRename(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName);
|
VOID FspFileNodeRename(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName);
|
||||||
VOID FspFileNodeGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo);
|
VOID FspFileNodeGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo);
|
||||||
BOOLEAN FspFileNodeTryGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo);
|
BOOLEAN FspFileNodeTryGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo);
|
||||||
@ -851,7 +852,7 @@ NTSTATUS FspFileNodeFlushAndPurgeCache(FSP_FILE_NODE *FileNode,
|
|||||||
return IoStatus.Status;
|
return IoStatus.Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define GATHER_DESCENDANTS(FILENAME, SUBPATHONLY, REFERENCE, ...)\
|
#define GATHER_DESCENDANTS(FILENAME, REFERENCE, ...)\
|
||||||
FSP_FILE_NODE *DescendantFileNode;\
|
FSP_FILE_NODE *DescendantFileNode;\
|
||||||
FSP_FILE_NODE *DescendantFileNodeArray[16], **DescendantFileNodes;\
|
FSP_FILE_NODE *DescendantFileNodeArray[16], **DescendantFileNodes;\
|
||||||
ULONG DescendantFileNodeCount, DescendantFileNodeIndex;\
|
ULONG DescendantFileNodeCount, DescendantFileNodeIndex;\
|
||||||
@ -862,7 +863,7 @@ NTSTATUS FspFileNodeFlushAndPurgeCache(FSP_FILE_NODE *FileNode,
|
|||||||
for (;;) \
|
for (;;) \
|
||||||
{ \
|
{ \
|
||||||
DescendantFileNode = FspFsvolDeviceEnumerateContextByName(FsvolDeviceObject,\
|
DescendantFileNode = FspFsvolDeviceEnumerateContextByName(FsvolDeviceObject,\
|
||||||
FILENAME, SUBPATHONLY, &RestartKey);\
|
FILENAME, FALSE, &RestartKey);\
|
||||||
if (0 == DescendantFileNode) \
|
if (0 == DescendantFileNode) \
|
||||||
break; \
|
break; \
|
||||||
ASSERT(0 == ((UINT_PTR)DescendantFileNode & 7));\
|
ASSERT(0 == ((UINT_PTR)DescendantFileNode & 7));\
|
||||||
@ -882,7 +883,7 @@ NTSTATUS FspFileNodeFlushAndPurgeCache(FSP_FILE_NODE *FileNode,
|
|||||||
for (;;) \
|
for (;;) \
|
||||||
{ \
|
{ \
|
||||||
DescendantFileNode = FspFsvolDeviceEnumerateContextByName(FsvolDeviceObject,\
|
DescendantFileNode = FspFsvolDeviceEnumerateContextByName(FsvolDeviceObject,\
|
||||||
FILENAME, SUBPATHONLY, &RestartKey);\
|
FILENAME, FALSE, &RestartKey);\
|
||||||
if (0 == DescendantFileNode)\
|
if (0 == DescendantFileNode)\
|
||||||
break; \
|
break; \
|
||||||
ASSERT(0 == ((UINT_PTR)DescendantFileNode & 7));\
|
ASSERT(0 == ((UINT_PTR)DescendantFileNode & 7));\
|
||||||
@ -934,7 +935,7 @@ NTSTATUS FspFileNodeCheckBatchOplocksOnAllStreams(
|
|||||||
|
|
||||||
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
|
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
|
||||||
|
|
||||||
GATHER_DESCENDANTS(&FileNode->FileName, FALSE, TRUE,
|
GATHER_DESCENDANTS(&FileNode->FileName, TRUE,
|
||||||
if (DescendantFileNode->FileName.Length > FileNameLength &&
|
if (DescendantFileNode->FileName.Length > FileNameLength &&
|
||||||
L'\\' == DescendantFileNode->FileName.Buffer[FileNameLength / sizeof(WCHAR)])
|
L'\\' == DescendantFileNode->FileName.Buffer[FileNameLength / sizeof(WCHAR)])
|
||||||
break;
|
break;
|
||||||
@ -1028,42 +1029,36 @@ NTSTATUS FspFileNodeCheckBatchOplocksOnAllStreams(
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOLEAN FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp,
|
NTSTATUS FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp,
|
||||||
FSP_FILE_NODE *FileNode, PUNICODE_STRING FileName)
|
FSP_FILE_NODE *FileNode, ULONG AcquireFlags,
|
||||||
|
PUNICODE_STRING FileName, BOOLEAN CheckingOldName)
|
||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
BOOLEAN CheckingOldName = 0 != FileNode;
|
NTSTATUS Result;
|
||||||
BOOLEAN HasOpenHandles;
|
ULONG HasHandles, IsBatchOplock, IsHandleOplock;
|
||||||
BOOLEAN Success = TRUE;
|
|
||||||
|
|
||||||
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
|
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
|
||||||
|
|
||||||
/* if we are checking the existing file name, do a quick check here */
|
if (CheckingOldName && !FileNode->IsDirectory && 1 == FileNode->HandleCount)
|
||||||
if (CheckingOldName)
|
|
||||||
{
|
|
||||||
/* if file has single open handle (also means no streams open) and not a directory, exit now */
|
|
||||||
if (1 == FileNode->HandleCount && !FileNode->IsDirectory)
|
|
||||||
{
|
{
|
||||||
|
/* quick exit */
|
||||||
FspFsvolDeviceUnlockContextTable(FsvolDeviceObject);
|
FspFsvolDeviceUnlockContextTable(FsvolDeviceObject);
|
||||||
return TRUE;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note: when CheckingOldName==TRUE, the old FileNode is not included in enumerations below */
|
GATHER_DESCENDANTS(FileName, TRUE,
|
||||||
}
|
|
||||||
|
|
||||||
GATHER_DESCENDANTS(FileName, CheckingOldName, TRUE,
|
|
||||||
DescendantFileNode = (PVOID)((UINT_PTR)DescendantFileNode |
|
DescendantFileNode = (PVOID)((UINT_PTR)DescendantFileNode |
|
||||||
(0 < DescendantFileNode->HandleCount)));
|
(0 < DescendantFileNode->HandleCount)));
|
||||||
|
|
||||||
|
FspFsvolDeviceUnlockContextTable(FsvolDeviceObject);
|
||||||
|
|
||||||
if (0 == DescendantFileNodeCount)
|
if (0 == DescendantFileNodeCount)
|
||||||
{
|
{
|
||||||
ASSERT(Success);
|
Result = STATUS_SUCCESS;
|
||||||
goto unlock_exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
FspFsvolDeviceUnlockContextTable(FsvolDeviceObject);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* At this point all descendant FileNode's are enumerated and referenced.
|
* At this point all descendant FileNode's are enumerated and referenced.
|
||||||
* There can be no new FileNode's because Rename has acquired the device's
|
* There can be no new FileNode's because Rename has acquired the device's
|
||||||
@ -1079,29 +1074,103 @@ BOOLEAN FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp,
|
|||||||
DescendantFileNodeIndex++)
|
DescendantFileNodeIndex++)
|
||||||
{
|
{
|
||||||
DescendantFileNode = DescendantFileNodes[DescendantFileNodeIndex];
|
DescendantFileNode = DescendantFileNodes[DescendantFileNodeIndex];
|
||||||
DescendantFileNode = (PVOID)((UINT_PTR)DescendantFileNode & ~1);
|
DescendantFileNode = (PVOID)((UINT_PTR)DescendantFileNode & ~7);
|
||||||
|
|
||||||
Success = MmFlushImageSection(&DescendantFileNode->NonPaged->SectionObjectPointers,
|
if (!MmFlushImageSection(&DescendantFileNode->NonPaged->SectionObjectPointers,
|
||||||
MmFlushForDelete);
|
MmFlushForDelete))
|
||||||
if (!Success)
|
{
|
||||||
goto unlock_exit;
|
/* release the FileNode in case of failure! */
|
||||||
|
FspFileNodeReleaseF(FileNode, AcquireFlags);
|
||||||
|
|
||||||
|
Result = STATUS_ACCESS_DENIED;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* break any Batch or Handle oplocks on descendants */
|
/* break any Batch or Handle oplocks on descendants */
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
for (
|
for (
|
||||||
DescendantFileNodeIndex = 0;
|
DescendantFileNodeIndex = 0;
|
||||||
DescendantFileNodeCount > DescendantFileNodeIndex;
|
DescendantFileNodeCount > DescendantFileNodeIndex;
|
||||||
DescendantFileNodeIndex++)
|
DescendantFileNodeIndex++)
|
||||||
{
|
{
|
||||||
DescendantFileNode = DescendantFileNodes[DescendantFileNodeIndex];
|
DescendantFileNode = DescendantFileNodes[DescendantFileNodeIndex];
|
||||||
HasOpenHandles = (UINT_PTR)DescendantFileNode & 1;
|
HasHandles = (UINT_PTR)DescendantFileNode & 1;
|
||||||
DescendantFileNode = (PVOID)((UINT_PTR)DescendantFileNode & ~1);
|
DescendantFileNode = (PVOID)((UINT_PTR)DescendantFileNode & ~7);
|
||||||
|
|
||||||
if (HasOpenHandles)
|
if (!HasHandles)
|
||||||
if (FspFileNodeOplockIsBatch(DescendantFileNode) ||
|
continue;
|
||||||
FspFileNodeOplockIsHandle(DescendantFileNode))
|
|
||||||
FspFileNodeOplockCheck(DescendantFileNode, OplockIrp);
|
if (FspFileNodeOplockIsBatch(DescendantFileNode))
|
||||||
|
{
|
||||||
|
NTSTATUS Result0 = FspFileNodeOplockCheckEx(DescendantFileNode, OplockIrp,
|
||||||
|
OPLOCK_FLAG_COMPLETE_IF_OPLOCKED);
|
||||||
|
if (STATUS_SUCCESS == Result0)
|
||||||
|
Result = NT_SUCCESS(Result) ? STATUS_OPLOCK_BREAK_IN_PROGRESS : Result;
|
||||||
|
else
|
||||||
|
if (STATUS_OPLOCK_BREAK_IN_PROGRESS == Result0)
|
||||||
|
{
|
||||||
|
Result = NT_SUCCESS(Result) ? STATUS_OPLOCK_BREAK_IN_PROGRESS : Result;
|
||||||
|
DescendantFileNodes[DescendantFileNodeIndex] =
|
||||||
|
(PVOID)((UINT_PTR)DescendantFileNode | 2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Result = STATUS_ACCESS_DENIED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (FspFileNodeOplockIsHandle(DescendantFileNode))
|
||||||
|
{
|
||||||
|
NTSTATUS Result0 = FspFileNodeOplockBreakHandle(DescendantFileNode, OplockIrp,
|
||||||
|
OPLOCK_FLAG_COMPLETE_IF_OPLOCKED);
|
||||||
|
if (STATUS_SUCCESS == Result0)
|
||||||
|
Result = NT_SUCCESS(Result) ? STATUS_OPLOCK_BREAK_IN_PROGRESS : Result;
|
||||||
|
else
|
||||||
|
if (STATUS_OPLOCK_BREAK_IN_PROGRESS == Result0)
|
||||||
|
{
|
||||||
|
Result = NT_SUCCESS(Result) ? STATUS_OPLOCK_BREAK_IN_PROGRESS : Result;
|
||||||
|
DescendantFileNodes[DescendantFileNodeIndex] =
|
||||||
|
(PVOID)((UINT_PTR)DescendantFileNode | 2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Result = STATUS_ACCESS_DENIED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (STATUS_OPLOCK_BREAK_IN_PROGRESS == Result || !NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
/* release the FileNode so that we can safely wait without deadlocks */
|
||||||
|
FspFileNodeReleaseF(FileNode, AcquireFlags);
|
||||||
|
|
||||||
|
/* wait for oplock breaks to finish */
|
||||||
|
for (
|
||||||
|
DescendantFileNodeIndex = 0;
|
||||||
|
DescendantFileNodeCount > DescendantFileNodeIndex;
|
||||||
|
DescendantFileNodeIndex++)
|
||||||
|
{
|
||||||
|
DescendantFileNode = DescendantFileNodes[DescendantFileNodeIndex];
|
||||||
|
IsBatchOplock = (UINT_PTR)DescendantFileNode & 2;
|
||||||
|
IsHandleOplock = (UINT_PTR)DescendantFileNode & 4;
|
||||||
|
DescendantFileNode = (PVOID)((UINT_PTR)DescendantFileNode & ~7);
|
||||||
|
|
||||||
|
if (IsBatchOplock)
|
||||||
|
{
|
||||||
|
NTSTATUS Result0 = FspFileNodeOplockCheck(DescendantFileNode, OplockIrp);
|
||||||
|
ASSERT(STATUS_OPLOCK_BREAK_IN_PROGRESS != Result0);
|
||||||
|
if (STATUS_SUCCESS != Result0)
|
||||||
|
Result = STATUS_ACCESS_DENIED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (IsHandleOplock)
|
||||||
|
{
|
||||||
|
NTSTATUS Result0 = FspFileNodeOplockBreakHandle(DescendantFileNode, OplockIrp, 0);
|
||||||
|
ASSERT(STATUS_OPLOCK_BREAK_IN_PROGRESS != Result0);
|
||||||
|
if (STATUS_SUCCESS != Result0)
|
||||||
|
Result = STATUS_ACCESS_DENIED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
|
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
|
||||||
@ -1111,23 +1180,27 @@ BOOLEAN FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp,
|
|||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
DescendantFileNode = FspFsvolDeviceEnumerateContextByName(FsvolDeviceObject,
|
DescendantFileNode = FspFsvolDeviceEnumerateContextByName(FsvolDeviceObject,
|
||||||
FileName, CheckingOldName, &RestartKey);
|
FileName, FALSE, &RestartKey);
|
||||||
if (0 == DescendantFileNode)
|
if (0 == DescendantFileNode)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (0 < DescendantFileNode->HandleCount)
|
/* if this is the FileNode being renamed then HandleCount must be 1, else 0 */
|
||||||
|
if ((DescendantFileNode == FileNode) < DescendantFileNode->HandleCount)
|
||||||
{
|
{
|
||||||
Success = FALSE;
|
/* release the FileNode in case of failure! */
|
||||||
goto unlock_exit;
|
FspFileNodeReleaseF(FileNode, AcquireFlags);
|
||||||
|
|
||||||
|
Result = STATUS_ACCESS_DENIED;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unlock_exit:
|
|
||||||
FspFsvolDeviceUnlockContextTable(FsvolDeviceObject);
|
FspFsvolDeviceUnlockContextTable(FsvolDeviceObject);
|
||||||
|
|
||||||
|
exit:
|
||||||
SCATTER_DESCENDANTS(TRUE);
|
SCATTER_DESCENDANTS(TRUE);
|
||||||
|
|
||||||
return Success;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID FspFileNodeRename(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName)
|
VOID FspFileNodeRename(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName)
|
||||||
@ -1160,7 +1233,7 @@ VOID FspFileNodeRename(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName)
|
|||||||
|
|
||||||
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
|
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
|
||||||
|
|
||||||
GATHER_DESCENDANTS(&FileNode->FileName, FALSE, FALSE, {});
|
GATHER_DESCENDANTS(&FileNode->FileName, FALSE, {});
|
||||||
|
|
||||||
FileNameLength = FileNode->FileName.Length;
|
FileNameLength = FileNode->FileName.Length;
|
||||||
for (
|
for (
|
||||||
|
@ -1159,7 +1159,7 @@ static NTSTATUS FspFsvolSetRenameInformation(
|
|||||||
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
|
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
|
||||||
FSP_FILE_NODE *TargetFileNode = 0 != TargetFileObject ?
|
FSP_FILE_NODE *TargetFileNode = 0 != TargetFileObject ?
|
||||||
TargetFileObject->FsContext : 0;
|
TargetFileObject->FsContext : 0;
|
||||||
FSP_FSCTL_TRANSACT_REQ *Request;
|
FSP_FSCTL_TRANSACT_REQ *Request = 0;
|
||||||
UNICODE_STRING Remain, Suffix;
|
UNICODE_STRING Remain, Suffix;
|
||||||
UNICODE_STRING NewFileName;
|
UNICODE_STRING NewFileName;
|
||||||
PUINT8 NewFileNameBuffer;
|
PUINT8 NewFileNameBuffer;
|
||||||
@ -1186,37 +1186,12 @@ static NTSTATUS FspFsvolSetRenameInformation(
|
|||||||
ASSERT(TargetFileNode->IsDirectory);
|
ASSERT(TargetFileNode->IsDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
retry:
|
|
||||||
FspFsvolDeviceFileRenameAcquireExclusive(FsvolDeviceObject);
|
FspFsvolDeviceFileRenameAcquireExclusive(FsvolDeviceObject);
|
||||||
|
retry:
|
||||||
FspFileNodeAcquireExclusive(FileNode, Full);
|
FspFileNodeAcquireExclusive(FileNode, Full);
|
||||||
|
|
||||||
/*
|
if (0 == Request)
|
||||||
* Perform oplock check.
|
|
||||||
*
|
|
||||||
* It is ok to block our thread during receipt of the SetInformation IRP.
|
|
||||||
* However we cannot acquire the FileNode exclusive and wait for oplock
|
|
||||||
* breaks to complete, because oplock break processing acquires the FileNode
|
|
||||||
* shared.
|
|
||||||
*
|
|
||||||
* Instead we initiate the oplock breaks and then check if any are in progress.
|
|
||||||
* If that is the case we release the FileNode and wait for the oplock breaks
|
|
||||||
* to complete. Once they are complete we retry the whole thing.
|
|
||||||
*/
|
|
||||||
Result = FspFileNodeOplockCheckEx(FileNode, Irp,
|
|
||||||
OPLOCK_FLAG_COMPLETE_IF_OPLOCKED);
|
|
||||||
if (STATUS_OPLOCK_BREAK_IN_PROGRESS == Result ||
|
|
||||||
DEBUGTEST_EX(NT_SUCCESS(Result), 10, FALSE))
|
|
||||||
{
|
{
|
||||||
FspFileNodeRelease(FileNode, Full);
|
|
||||||
FspFsvolDeviceFileRenameRelease(FsvolDeviceObject);
|
|
||||||
Result = FspFileNodeOplockCheck(FileNode, Irp);
|
|
||||||
if (!NT_SUCCESS(Result))
|
|
||||||
return Result;
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
if (!NT_SUCCESS(Result))
|
|
||||||
goto unlock_exit;
|
|
||||||
|
|
||||||
if (0 != TargetFileNode)
|
if (0 != TargetFileNode)
|
||||||
Remain = TargetFileNode->FileName;
|
Remain = TargetFileNode->FileName;
|
||||||
else
|
else
|
||||||
@ -1265,11 +1240,7 @@ retry:
|
|||||||
Request->Req.SetInformation.FileInformationClass = FileRenameInformation;
|
Request->Req.SetInformation.FileInformationClass = FileRenameInformation;
|
||||||
Request->Req.SetInformation.Info.Rename.NewFileName.Offset = Request->FileName.Size;
|
Request->Req.SetInformation.Info.Rename.NewFileName.Offset = Request->FileName.Size;
|
||||||
Request->Req.SetInformation.Info.Rename.NewFileName.Size = NewFileName.Length + sizeof(WCHAR);
|
Request->Req.SetInformation.Info.Rename.NewFileName.Size = NewFileName.Length + sizeof(WCHAR);
|
||||||
|
}
|
||||||
FspFsvolDeviceFileRenameSetOwner(FsvolDeviceObject, Request);
|
|
||||||
FspFileNodeSetOwner(FileNode, Full, Request);
|
|
||||||
FspIopRequestContext(Request, RequestFileNode) = FileNode;
|
|
||||||
FspIopRequestContext(Request, RequestDeviceObject) = FsvolDeviceObject;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Special rules for renaming open files:
|
* Special rules for renaming open files:
|
||||||
@ -1281,14 +1252,35 @@ retry:
|
|||||||
* - A directory cannot be renamed if it or any of its subdirectories contains a file
|
* - A directory cannot be renamed if it or any of its subdirectories contains a file
|
||||||
* that has open handles (except in the batch-oplock case described earlier).
|
* that has open handles (except in the batch-oplock case described earlier).
|
||||||
*/
|
*/
|
||||||
Result = STATUS_SUCCESS;
|
|
||||||
if (!FspFileNodeRenameCheck(FsvolDeviceObject, Irp, FileNode, &FileNode->FileName) ||
|
|
||||||
(0 != FspFileNameCompare(&FileNode->FileName, &NewFileName, !FileDesc->CaseSensitive, 0) &&
|
|
||||||
!FspFileNodeRenameCheck(FsvolDeviceObject, Irp, 0, &NewFileName)))
|
|
||||||
Result = STATUS_ACCESS_DENIED;
|
|
||||||
if (!NT_SUCCESS(Result))
|
|
||||||
return Result;
|
|
||||||
|
|
||||||
|
Result = FspFileNodeRenameCheck(FsvolDeviceObject, Irp,
|
||||||
|
FileNode, FspFileNodeAcquireFull,
|
||||||
|
&FileNode->FileName, TRUE);
|
||||||
|
/* FspFileNodeRenameCheck releases FileNode with STATUS_OPLOCK_BREAK_IN_PROGRESS or failure */
|
||||||
|
if (STATUS_OPLOCK_BREAK_IN_PROGRESS == Result)
|
||||||
|
goto retry;
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
Result = STATUS_ACCESS_DENIED;
|
||||||
|
goto rename_unlock_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 != FspFileNameCompare(&FileNode->FileName, &NewFileName, !FileDesc->CaseSensitive, 0))
|
||||||
|
{
|
||||||
|
Result = FspFileNodeRenameCheck(FsvolDeviceObject, Irp,
|
||||||
|
FileNode, FspFileNodeAcquireFull,
|
||||||
|
&NewFileName, FALSE);
|
||||||
|
/* FspFileNodeRenameCheck releases FileNode with STATUS_OPLOCK_BREAK_IN_PROGRESS or failure */
|
||||||
|
if (STATUS_OPLOCK_BREAK_IN_PROGRESS == Result)
|
||||||
|
goto retry;
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
Result = STATUS_ACCESS_DENIED;
|
||||||
|
goto rename_unlock_exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* If the new file name is *exactly* the same (including case) as the old one,
|
* If the new file name is *exactly* the same (including case) as the old one,
|
||||||
* there is no need to go to the user mode file system. Just return STATUS_SUCCESS.
|
* there is no need to go to the user mode file system. Just return STATUS_SUCCESS.
|
||||||
@ -1298,12 +1290,22 @@ retry:
|
|||||||
* and NTFS do.
|
* and NTFS do.
|
||||||
*/
|
*/
|
||||||
if (0 == FspFileNameCompare(&FileNode->FileName, &NewFileName, FALSE, 0))
|
if (0 == FspFileNameCompare(&FileNode->FileName, &NewFileName, FALSE, 0))
|
||||||
return STATUS_SUCCESS;
|
{
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
goto unlock_exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FspFsvolDeviceFileRenameSetOwner(FsvolDeviceObject, Request);
|
||||||
|
FspFileNodeSetOwner(FileNode, Full, Request);
|
||||||
|
FspIopRequestContext(Request, RequestFileNode) = FileNode;
|
||||||
|
FspIopRequestContext(Request, RequestDeviceObject) = FsvolDeviceObject;
|
||||||
|
|
||||||
return FSP_STATUS_IOQ_POST;
|
return FSP_STATUS_IOQ_POST;
|
||||||
|
|
||||||
unlock_exit:
|
unlock_exit:
|
||||||
FspFileNodeRelease(FileNode, Full);
|
FspFileNodeRelease(FileNode, Full);
|
||||||
|
rename_unlock_exit:
|
||||||
FspFsvolDeviceFileRenameRelease(FsvolDeviceObject);
|
FspFsvolDeviceFileRenameRelease(FsvolDeviceObject);
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user