mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-22 16:33:02 -05:00
dll: dotnet: revert the Delete redesign
This commit is contained in:
parent
a9d90acd71
commit
826a514fe3
@ -1001,19 +1001,10 @@ FSP_API NTSTATUS FspFileSystemOpCleanup(FSP_FILE_SYSTEM *FileSystem,
|
||||
|
||||
if (Request->Req.Cleanup.Delete && 0 != FileSystem->Interface->Delete)
|
||||
{
|
||||
NTSTATUS Result = FileSystem->Interface->Delete(FileSystem,
|
||||
FileSystem->Interface->Delete(FileSystem,
|
||||
(PVOID)ValOfFileContext(Request->Req.Cleanup),
|
||||
0 != Request->FileName.Size ? (PWSTR)Request->Buffer : 0,
|
||||
(ULONG)-1);
|
||||
/*
|
||||
* If Delete returns STATUS_NOT_IMPLEMENTED it means that it is unable
|
||||
* to handle file deletion during the Cleanup phase. In this case we
|
||||
* will handle file deletion in Cleanup with the FspCleanupDelete flag.
|
||||
*
|
||||
* This is necessary for file systems like the .NET layer where Delete
|
||||
* may be implemented but unable to handle all file deletion cases.
|
||||
*/
|
||||
if (STATUS_NOT_IMPLEMENTED != Result)
|
||||
CleanupFlags &= ~FspCleanupDelete;
|
||||
}
|
||||
|
||||
|
@ -57,14 +57,6 @@ namespace Fsp
|
||||
public const UInt32 CleanupSetLastWriteTime = 0x40;
|
||||
public const UInt32 CleanupSetChangeTime = 0x80;
|
||||
|
||||
/* Disposition */
|
||||
public const UInt32 FILE_DISPOSITION_DO_NOT_DELETE = 0x00000000;
|
||||
public const UInt32 FILE_DISPOSITION_DELETE = 0x00000001;
|
||||
public const UInt32 FILE_DISPOSITION_POSIX_SEMANTICS = 0x00000002;
|
||||
public const UInt32 FILE_DISPOSITION_FORCE_IMAGE_SECTION_CHECK = 0x00000004;
|
||||
public const UInt32 FILE_DISPOSITION_ON_CLOSE = 0x00000008;
|
||||
public const UInt32 FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE = 0x00000010;
|
||||
|
||||
/* NTSTATUS */
|
||||
public const Int32 STATUS_SUCCESS = unchecked((Int32)0x00000000);
|
||||
public const Int32 STATUS_WAIT_1 = unchecked((Int32)0x00000001);
|
||||
|
@ -289,9 +289,6 @@ namespace Fsp
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// (NOTE: use of this function with the CleanupDelete flag is not recommended;
|
||||
/// use Delete instead.)
|
||||
/// </para><para>
|
||||
/// When CreateFile is used to open or create a file the kernel creates a kernel mode file
|
||||
/// object (type FILE_OBJECT) and a handle for it, which it returns to user-mode. The handle may
|
||||
/// be duplicated (using DuplicateHandle), but all duplicate handles always refer to the same
|
||||
@ -345,7 +342,6 @@ namespace Fsp
|
||||
/// </param>
|
||||
/// <seealso cref="CanDelete"/>
|
||||
/// <seealso cref="SetDelete"/>
|
||||
/// <seealso cref="Delete"/>
|
||||
/// <seealso cref="Close"/>
|
||||
public virtual void Cleanup(
|
||||
Object FileNode,
|
||||
@ -602,8 +598,6 @@ namespace Fsp
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// (NOTE: use of this function is not recommended; use Delete instead.)
|
||||
/// </para><para>
|
||||
/// This function tests whether a file or directory can be safely deleted. This function does
|
||||
/// not need to perform access checks, but may performs tasks such as check for empty
|
||||
/// directories, etc.
|
||||
@ -630,7 +624,6 @@ namespace Fsp
|
||||
/// <returns>STATUS_SUCCESS or error code.</returns>
|
||||
/// <seealso cref="Cleanup"/>
|
||||
/// <seealso cref="SetDelete"/>
|
||||
/// <seealso cref="Delete"/>
|
||||
public virtual Int32 CanDelete(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
@ -1043,8 +1036,6 @@ namespace Fsp
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// (NOTE: use of this function is not recommended; use Delete instead.)
|
||||
/// </para><para>
|
||||
/// This function sets a flag to indicates whether the FSD file should delete a file
|
||||
/// when it is closed. This function does not need to perform access checks, but may
|
||||
/// performs tasks such as check for empty directories, etc.
|
||||
@ -1076,7 +1067,6 @@ namespace Fsp
|
||||
/// <returns>STATUS_SUCCESS or error code.</returns>
|
||||
/// <seealso cref="Cleanup"/>
|
||||
/// <seealso cref="CanDelete"/>
|
||||
/// <seealso cref="Delete"/>
|
||||
public virtual Int32 SetDelete(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
@ -1198,85 +1188,6 @@ namespace Fsp
|
||||
{
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
/// <summary>
|
||||
/// Sets the file delete flag or deletes a file or directory.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This function replaces CanDelete, SetDelete and uses of Cleanup with the CleanupDelete flag
|
||||
/// and is recommended for use in all new code.
|
||||
/// </para><para>
|
||||
/// Due to the complexity of file deletion in the Windows file system this function is used
|
||||
/// in many scenarios. Its usage is controlled by the Flags parameter:
|
||||
/// <list>
|
||||
/// <item>FILE_DISPOSITION_DO_NOT_DELETE: Unmark the file for deletion.
|
||||
/// Do <b>NOT</b> delete the file either now or at Cleanup time.</item>
|
||||
/// <item>FILE_DISPOSITION_DELETE: Mark the file for deletion,
|
||||
/// but do <b>NOT</b> delete the file. The file will be deleted at Cleanup time
|
||||
/// (via a call to Delete with Flags = -1).
|
||||
/// This function does not need to perform access checks, but may
|
||||
/// performs tasks such as check for empty directories, etc.</item>
|
||||
/// <item>FILE_DISPOSITION_DELETE | FILE_DISPOSITION_POSIX_SEMANTICS: Delete the file
|
||||
/// <b>NOW</b> using POSIX semantics. Open user mode handles to the file remain valid.
|
||||
/// This case will be received only when SupportsPosixUnlinkRename is set.</item>
|
||||
/// <item>-1: Delete the file <b>NOW</b> using regular Windows semantics.
|
||||
/// Called during Cleanup with no open user mode handles remaining.
|
||||
/// If a file system implements Delete, Cleanup should <b>NOT</b> be used for deletion anymore.</item>
|
||||
/// </list>
|
||||
/// </para><para>
|
||||
/// This function gets called in all file deletion scenarios:
|
||||
/// <list>
|
||||
/// <item>When the DeleteFile or RemoveDirectory API's are used.</item>
|
||||
/// <item>When the SetInformationByHandle API with FileDispositionInfo or FileDispositionInfoEx is used.</item>
|
||||
/// <item>When a file is opened using FILE_DELETE_ON_CLOSE.</item>
|
||||
/// <item>Etc.</item>
|
||||
/// </list>
|
||||
/// </para><para>
|
||||
/// NOTE: Delete takes precedence over CanDelete, SetDelete and Cleanup with the CleanupDelete flag.
|
||||
/// This means that if Delete is defined, CanDelete and SetDelete will never be called and
|
||||
/// Cleanup will never be called with the CleanupDelete flag.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <param name="FileNode">
|
||||
/// The file node of the file or directory.
|
||||
/// </param>
|
||||
/// <param name="FileDesc">
|
||||
/// The file descriptor of the file or directory.
|
||||
/// </param>
|
||||
/// <param name="FileName">
|
||||
/// The name of the file or directory.
|
||||
/// </param>
|
||||
/// <param name="Flags">
|
||||
/// File disposition flags.
|
||||
/// </param>
|
||||
/// <returns>STATUS_SUCCESS or error code.</returns>
|
||||
/// <seealso cref="Cleanup"/>
|
||||
/// <seealso cref="CanDelete"/>
|
||||
/// <seealso cref="SetDelete"/>
|
||||
public virtual Int32 Delete(
|
||||
Object FileNode,
|
||||
Object FileDesc,
|
||||
String FileName,
|
||||
UInt32 Flags)
|
||||
{
|
||||
switch (Flags)
|
||||
{
|
||||
case FILE_DISPOSITION_DO_NOT_DELETE:
|
||||
return SetDelete(FileNode, FileDesc, FileName, false);
|
||||
|
||||
case FILE_DISPOSITION_DELETE:
|
||||
return SetDelete(FileNode, FileDesc, FileName, true);
|
||||
|
||||
case FILE_DISPOSITION_DELETE | FILE_DISPOSITION_POSIX_SEMANTICS:
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
case ~(UInt32)0:
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
|
||||
default:
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
/* helpers */
|
||||
/// <summary>
|
||||
|
@ -1348,6 +1348,28 @@ namespace Fsp
|
||||
return ExceptionHandler(FileSystem, ex);
|
||||
}
|
||||
}
|
||||
private static Int32 SetDelete(
|
||||
IntPtr FileSystemPtr,
|
||||
ref FullContext FullContext,
|
||||
String FileName,
|
||||
Boolean DeleteFile)
|
||||
{
|
||||
FileSystemBase FileSystem = (FileSystemBase)Api.GetUserContext(FileSystemPtr);
|
||||
try
|
||||
{
|
||||
Object FileNode, FileDesc;
|
||||
Api.GetFullContext(ref FullContext, out FileNode, out FileDesc);
|
||||
return FileSystem.SetDelete(
|
||||
FileNode,
|
||||
FileDesc,
|
||||
FileName,
|
||||
DeleteFile);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return ExceptionHandler(FileSystem, ex);
|
||||
}
|
||||
}
|
||||
private static Int32 GetEa(
|
||||
IntPtr FileSystemPtr,
|
||||
ref FullContext FullContext,
|
||||
@ -1398,28 +1420,6 @@ namespace Fsp
|
||||
return ExceptionHandler(FileSystem, ex);
|
||||
}
|
||||
}
|
||||
private static Int32 Delete(
|
||||
IntPtr FileSystemPtr,
|
||||
ref FullContext FullContext,
|
||||
String FileName,
|
||||
UInt32 Flags)
|
||||
{
|
||||
FileSystemBase FileSystem = (FileSystemBase)Api.GetUserContext(FileSystemPtr);
|
||||
try
|
||||
{
|
||||
Object FileNode, FileDesc;
|
||||
Api.GetFullContext(ref FullContext, out FileNode, out FileDesc);
|
||||
return FileSystem.Delete(
|
||||
FileNode,
|
||||
FileDesc,
|
||||
FileName,
|
||||
Flags);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return ExceptionHandler(FileSystem, ex);
|
||||
}
|
||||
}
|
||||
|
||||
static FileSystemHost()
|
||||
{
|
||||
@ -1448,9 +1448,9 @@ namespace Fsp
|
||||
_FileSystemInterface.GetStreamInfo = GetStreamInfo;
|
||||
_FileSystemInterface.GetDirInfoByName = GetDirInfoByName;
|
||||
_FileSystemInterface.Control = Control;
|
||||
_FileSystemInterface.SetDelete = SetDelete;
|
||||
_FileSystemInterface.GetEa = GetEa;
|
||||
_FileSystemInterface.SetEa = SetEa;
|
||||
_FileSystemInterface.Delete = Delete;
|
||||
|
||||
_FileSystemInterfacePtr = Marshal.AllocHGlobal(FileSystemInterface.Size);
|
||||
/* Marshal.AllocHGlobal does not zero memory; we must do it ourselves! */
|
||||
|
@ -743,11 +743,7 @@ namespace Fsp.Interop
|
||||
UInt32 EaLength,
|
||||
out FileInfo FileInfo);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate Int32 Delete(
|
||||
IntPtr FileSystem,
|
||||
ref FullContext FullContext,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] String FileName,
|
||||
UInt32 Flags);
|
||||
internal delegate Int32 Obsolete0();
|
||||
}
|
||||
|
||||
internal static int Size = IntPtr.Size * 64;
|
||||
@ -783,8 +779,8 @@ namespace Fsp.Interop
|
||||
internal Proto.OverwriteEx OverwriteEx;
|
||||
internal Proto.GetEa GetEa;
|
||||
internal Proto.SetEa SetEa;
|
||||
internal Proto.Delete Delete;
|
||||
/* NTSTATUS (*Reserved[32])(); */
|
||||
internal Proto.Obsolete0 Obsolete0;
|
||||
/* NTSTATUS (*Reserved[33])(); */
|
||||
}
|
||||
|
||||
[SuppressUnmanagedCodeSecurity]
|
||||
|
@ -564,6 +564,19 @@ namespace memfs
|
||||
AllocationUnit * AllocationUnit;
|
||||
SetFileSizeInternal(FileNode, AllocationSize, true);
|
||||
}
|
||||
|
||||
if (0 != (Flags & CleanupDelete) && !FileNodeMap.HasChild(FileNode))
|
||||
{
|
||||
List<String> StreamFileNames = new List<String>(FileNodeMap.GetStreamFileNames(FileNode));
|
||||
foreach (String StreamFileName in StreamFileNames)
|
||||
{
|
||||
FileNode StreamNode = FileNodeMap.Get(StreamFileName);
|
||||
if (null == StreamNode)
|
||||
continue; /* should not happen */
|
||||
FileNodeMap.Remove(StreamNode);
|
||||
}
|
||||
FileNodeMap.Remove(FileNode);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Close(
|
||||
@ -908,6 +921,19 @@ namespace memfs
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
public override Int32 CanDelete(
|
||||
Object FileNode0,
|
||||
Object FileDesc,
|
||||
String FileName)
|
||||
{
|
||||
FileNode FileNode = (FileNode)FileNode0;
|
||||
|
||||
if (FileNodeMap.HasChild(FileNode))
|
||||
return STATUS_DIRECTORY_NOT_EMPTY;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
public override Int32 Rename(
|
||||
Object FileNode0,
|
||||
Object FileDesc,
|
||||
@ -1305,45 +1331,6 @@ namespace memfs
|
||||
FileNode.FileInfo.EaSize = FileNode.FileInfo.EaSize + EaSizePlus - EaSizeMinus;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
public override Int32 Delete(
|
||||
Object FileNode0,
|
||||
Object FileDesc,
|
||||
String FileName,
|
||||
UInt32 Flags)
|
||||
{
|
||||
FileNode FileNode = (FileNode)FileNode0;
|
||||
|
||||
switch (Flags)
|
||||
{
|
||||
case FILE_DISPOSITION_DO_NOT_DELETE:
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
case FILE_DISPOSITION_DELETE:
|
||||
if (FileNodeMap.HasChild(FileNode))
|
||||
return STATUS_DIRECTORY_NOT_EMPTY;
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
case FILE_DISPOSITION_DELETE | FILE_DISPOSITION_POSIX_SEMANTICS:
|
||||
case ~(UInt32)0:
|
||||
if (FileNodeMap.HasChild(FileNode))
|
||||
return STATUS_DIRECTORY_NOT_EMPTY;
|
||||
|
||||
List<String> StreamFileNames = new List<String>(FileNodeMap.GetStreamFileNames(FileNode));
|
||||
foreach (String StreamFileName in StreamFileNames)
|
||||
{
|
||||
FileNode StreamNode = FileNodeMap.Get(StreamFileName);
|
||||
if (null == StreamNode)
|
||||
continue; /* should not happen */
|
||||
FileNodeMap.Remove(StreamNode);
|
||||
}
|
||||
|
||||
FileNodeMap.Remove(FileNode);
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
default:
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
private FileNodeMap FileNodeMap;
|
||||
private UInt32 MaxFileNodes;
|
||||
|
Loading…
x
Reference in New Issue
Block a user