sys: implement named stream open/close and related delete/share access issues

This commit is contained in:
Bill Zissimopoulos
2016-09-27 14:53:59 -07:00
parent 2ba46fdb71
commit 495fc7a5dc
7 changed files with 274 additions and 15 deletions

View File

@ -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)
{