mirror of
https://github.com/winfsp/winfsp.git
synced 2025-07-03 17:32:57 -05:00
sys: implement named stream open/close and related delete/share access issues
This commit is contained in:
@ -420,12 +420,37 @@ FSP_FILE_NODE *FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
||||
PAGED_CODE();
|
||||
|
||||
PDEVICE_OBJECT FsvolDeviceObject = FileNode->FsvolDeviceObject;
|
||||
FSP_FILE_NODE *OpenedFileNode;
|
||||
FSP_FILE_NODE *OpenedFileNode = 0;
|
||||
BOOLEAN Inserted, DeletePending;
|
||||
NTSTATUS Result;
|
||||
|
||||
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
|
||||
|
||||
/*
|
||||
* If this is a named stream we must also check with our main stream.
|
||||
* Note that FileNode->MainStreamFileNode and OpenedFileNode->MainStreamFileNode
|
||||
* will always be the same.
|
||||
*/
|
||||
if (0 != FileNode->MainStreamFileNode)
|
||||
{
|
||||
DeletePending = 0 != FileNode->MainStreamFileNode->DeletePending;
|
||||
MemoryBarrier();
|
||||
if (DeletePending)
|
||||
{
|
||||
Result = STATUS_DELETE_PENDING;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (0 < FileNode->MainStreamFileNode->MainStreamDenyDeleteCount)
|
||||
{
|
||||
if (FlagOn(GrantedAccess, DELETE))
|
||||
{
|
||||
Result = STATUS_SHARING_VIOLATION;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OpenedFileNode = FspFsvolDeviceInsertContextByName(FsvolDeviceObject,
|
||||
&FileNode->FileName, FileNode, &FileNode->ContextByNameElementStorage, &Inserted);
|
||||
ASSERT(0 != OpenedFileNode);
|
||||
@ -449,6 +474,7 @@ FSP_FILE_NODE *FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
||||
* opening a prior FileNode that we found in the table.
|
||||
*/
|
||||
ASSERT(OpenedFileNode != FileNode);
|
||||
ASSERT(OpenedFileNode->MainStreamFileNode == FileNode->MainStreamFileNode);
|
||||
|
||||
DeletePending = 0 != OpenedFileNode->DeletePending;
|
||||
MemoryBarrier();
|
||||
@ -458,6 +484,19 @@ FSP_FILE_NODE *FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* if this is a main stream check whether there is a named stream that denies delete */
|
||||
if (0 < OpenedFileNode->StreamDenyDeleteCount)
|
||||
{
|
||||
/* we must be the main stream! */
|
||||
ASSERT(0 == OpenedFileNode->MainStreamFileNode);
|
||||
|
||||
if (FlagOn(GrantedAccess, DELETE))
|
||||
{
|
||||
Result = STATUS_SHARING_VIOLATION;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* FastFat says to do the following on Vista and above.
|
||||
*
|
||||
@ -478,15 +517,33 @@ FSP_FILE_NODE *FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
||||
/* share access check */
|
||||
Result = IoCheckShareAccess(GrantedAccess, ShareAccess, FileObject,
|
||||
&OpenedFileNode->ShareAccess, TRUE);
|
||||
|
||||
exit:
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
if (0 != PResult)
|
||||
*PResult = Result;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
OpenedFileNode = 0;
|
||||
}
|
||||
/*
|
||||
* No more failures allowed at this point!
|
||||
* This is because we have potentially inserted a new FileNode into the Context table.
|
||||
* We also updated OpenedFileNode->ShareAccess in IoSetShareAccess/IoCheckShareAccess.
|
||||
*/
|
||||
|
||||
if (FileObject->DeleteAccess && !FileObject->SharedDelete)
|
||||
{
|
||||
if (0 == OpenedFileNode->MainStreamFileNode)
|
||||
OpenedFileNode->MainStreamDenyDeleteCount++;
|
||||
else
|
||||
OpenedFileNode->MainStreamFileNode->StreamDenyDeleteCount++;
|
||||
}
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
if (0 != PResult)
|
||||
*PResult = Result;
|
||||
|
||||
OpenedFileNode = 0;
|
||||
}
|
||||
|
||||
if (0 != OpenedFileNode)
|
||||
@ -556,6 +613,14 @@ VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject
|
||||
|
||||
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
|
||||
|
||||
if (FileObject->DeleteAccess && !FileObject->SharedDelete)
|
||||
{
|
||||
if (0 == FileNode->MainStreamFileNode)
|
||||
FileNode->MainStreamDenyDeleteCount--;
|
||||
else
|
||||
FileNode->MainStreamFileNode->StreamDenyDeleteCount--;
|
||||
}
|
||||
|
||||
IoRemoveShareAccess(FileObject, &FileNode->ShareAccess);
|
||||
|
||||
if (0 == --FileNode->HandleCount)
|
||||
@ -1088,6 +1153,8 @@ VOID FspFileDescDelete(FSP_FILE_DESC *FileDesc)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
FspMainStreamClose(FileDesc->MainStreamHandle, FileDesc->MainStreamObject);
|
||||
|
||||
if (0 != FileDesc->DirectoryPattern.Buffer &&
|
||||
FspFileDescDirectoryPatternMatchAll != FileDesc->DirectoryPattern.Buffer)
|
||||
{
|
||||
|
Reference in New Issue
Block a user