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,20 +1001,11 @@ FSP_API NTSTATUS FspFileSystemOpCleanup(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
|
|
||||||
if (Request->Req.Cleanup.Delete && 0 != FileSystem->Interface->Delete)
|
if (Request->Req.Cleanup.Delete && 0 != FileSystem->Interface->Delete)
|
||||||
{
|
{
|
||||||
NTSTATUS Result = FileSystem->Interface->Delete(FileSystem,
|
FileSystem->Interface->Delete(FileSystem,
|
||||||
(PVOID)ValOfFileContext(Request->Req.Cleanup),
|
(PVOID)ValOfFileContext(Request->Req.Cleanup),
|
||||||
0 != Request->FileName.Size ? (PWSTR)Request->Buffer : 0,
|
0 != Request->FileName.Size ? (PWSTR)Request->Buffer : 0,
|
||||||
(ULONG)-1);
|
(ULONG)-1);
|
||||||
/*
|
CleanupFlags &= ~FspCleanupDelete;
|
||||||
* 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 != FileSystem->Interface->Cleanup)
|
if (0 != FileSystem->Interface->Cleanup)
|
||||||
|
@ -57,14 +57,6 @@ namespace Fsp
|
|||||||
public const UInt32 CleanupSetLastWriteTime = 0x40;
|
public const UInt32 CleanupSetLastWriteTime = 0x40;
|
||||||
public const UInt32 CleanupSetChangeTime = 0x80;
|
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 */
|
/* NTSTATUS */
|
||||||
public const Int32 STATUS_SUCCESS = unchecked((Int32)0x00000000);
|
public const Int32 STATUS_SUCCESS = unchecked((Int32)0x00000000);
|
||||||
public const Int32 STATUS_WAIT_1 = unchecked((Int32)0x00000001);
|
public const Int32 STATUS_WAIT_1 = unchecked((Int32)0x00000001);
|
||||||
|
@ -289,9 +289,6 @@ namespace Fsp
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// <para>
|
/// <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
|
/// 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
|
/// 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
|
/// be duplicated (using DuplicateHandle), but all duplicate handles always refer to the same
|
||||||
@ -345,7 +342,6 @@ namespace Fsp
|
|||||||
/// </param>
|
/// </param>
|
||||||
/// <seealso cref="CanDelete"/>
|
/// <seealso cref="CanDelete"/>
|
||||||
/// <seealso cref="SetDelete"/>
|
/// <seealso cref="SetDelete"/>
|
||||||
/// <seealso cref="Delete"/>
|
|
||||||
/// <seealso cref="Close"/>
|
/// <seealso cref="Close"/>
|
||||||
public virtual void Cleanup(
|
public virtual void Cleanup(
|
||||||
Object FileNode,
|
Object FileNode,
|
||||||
@ -602,8 +598,6 @@ namespace Fsp
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// <para>
|
/// <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
|
/// 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
|
/// not need to perform access checks, but may performs tasks such as check for empty
|
||||||
/// directories, etc.
|
/// directories, etc.
|
||||||
@ -630,7 +624,6 @@ namespace Fsp
|
|||||||
/// <returns>STATUS_SUCCESS or error code.</returns>
|
/// <returns>STATUS_SUCCESS or error code.</returns>
|
||||||
/// <seealso cref="Cleanup"/>
|
/// <seealso cref="Cleanup"/>
|
||||||
/// <seealso cref="SetDelete"/>
|
/// <seealso cref="SetDelete"/>
|
||||||
/// <seealso cref="Delete"/>
|
|
||||||
public virtual Int32 CanDelete(
|
public virtual Int32 CanDelete(
|
||||||
Object FileNode,
|
Object FileNode,
|
||||||
Object FileDesc,
|
Object FileDesc,
|
||||||
@ -1043,8 +1036,6 @@ namespace Fsp
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// <para>
|
/// <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
|
/// 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
|
/// when it is closed. This function does not need to perform access checks, but may
|
||||||
/// performs tasks such as check for empty directories, etc.
|
/// performs tasks such as check for empty directories, etc.
|
||||||
@ -1076,7 +1067,6 @@ namespace Fsp
|
|||||||
/// <returns>STATUS_SUCCESS or error code.</returns>
|
/// <returns>STATUS_SUCCESS or error code.</returns>
|
||||||
/// <seealso cref="Cleanup"/>
|
/// <seealso cref="Cleanup"/>
|
||||||
/// <seealso cref="CanDelete"/>
|
/// <seealso cref="CanDelete"/>
|
||||||
/// <seealso cref="Delete"/>
|
|
||||||
public virtual Int32 SetDelete(
|
public virtual Int32 SetDelete(
|
||||||
Object FileNode,
|
Object FileNode,
|
||||||
Object FileDesc,
|
Object FileDesc,
|
||||||
@ -1198,85 +1188,6 @@ namespace Fsp
|
|||||||
{
|
{
|
||||||
return STATUS_INVALID_DEVICE_REQUEST;
|
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 */
|
/* helpers */
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -1348,6 +1348,28 @@ namespace Fsp
|
|||||||
return ExceptionHandler(FileSystem, ex);
|
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(
|
private static Int32 GetEa(
|
||||||
IntPtr FileSystemPtr,
|
IntPtr FileSystemPtr,
|
||||||
ref FullContext FullContext,
|
ref FullContext FullContext,
|
||||||
@ -1398,28 +1420,6 @@ namespace Fsp
|
|||||||
return ExceptionHandler(FileSystem, ex);
|
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()
|
static FileSystemHost()
|
||||||
{
|
{
|
||||||
@ -1448,9 +1448,9 @@ namespace Fsp
|
|||||||
_FileSystemInterface.GetStreamInfo = GetStreamInfo;
|
_FileSystemInterface.GetStreamInfo = GetStreamInfo;
|
||||||
_FileSystemInterface.GetDirInfoByName = GetDirInfoByName;
|
_FileSystemInterface.GetDirInfoByName = GetDirInfoByName;
|
||||||
_FileSystemInterface.Control = Control;
|
_FileSystemInterface.Control = Control;
|
||||||
|
_FileSystemInterface.SetDelete = SetDelete;
|
||||||
_FileSystemInterface.GetEa = GetEa;
|
_FileSystemInterface.GetEa = GetEa;
|
||||||
_FileSystemInterface.SetEa = SetEa;
|
_FileSystemInterface.SetEa = SetEa;
|
||||||
_FileSystemInterface.Delete = Delete;
|
|
||||||
|
|
||||||
_FileSystemInterfacePtr = Marshal.AllocHGlobal(FileSystemInterface.Size);
|
_FileSystemInterfacePtr = Marshal.AllocHGlobal(FileSystemInterface.Size);
|
||||||
/* Marshal.AllocHGlobal does not zero memory; we must do it ourselves! */
|
/* Marshal.AllocHGlobal does not zero memory; we must do it ourselves! */
|
||||||
|
@ -743,11 +743,7 @@ namespace Fsp.Interop
|
|||||||
UInt32 EaLength,
|
UInt32 EaLength,
|
||||||
out FileInfo FileInfo);
|
out FileInfo FileInfo);
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
internal delegate Int32 Delete(
|
internal delegate Int32 Obsolete0();
|
||||||
IntPtr FileSystem,
|
|
||||||
ref FullContext FullContext,
|
|
||||||
[MarshalAs(UnmanagedType.LPWStr)] String FileName,
|
|
||||||
UInt32 Flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static int Size = IntPtr.Size * 64;
|
internal static int Size = IntPtr.Size * 64;
|
||||||
@ -783,8 +779,8 @@ namespace Fsp.Interop
|
|||||||
internal Proto.OverwriteEx OverwriteEx;
|
internal Proto.OverwriteEx OverwriteEx;
|
||||||
internal Proto.GetEa GetEa;
|
internal Proto.GetEa GetEa;
|
||||||
internal Proto.SetEa SetEa;
|
internal Proto.SetEa SetEa;
|
||||||
internal Proto.Delete Delete;
|
internal Proto.Obsolete0 Obsolete0;
|
||||||
/* NTSTATUS (*Reserved[32])(); */
|
/* NTSTATUS (*Reserved[33])(); */
|
||||||
}
|
}
|
||||||
|
|
||||||
[SuppressUnmanagedCodeSecurity]
|
[SuppressUnmanagedCodeSecurity]
|
||||||
|
@ -564,6 +564,19 @@ namespace memfs
|
|||||||
AllocationUnit * AllocationUnit;
|
AllocationUnit * AllocationUnit;
|
||||||
SetFileSizeInternal(FileNode, AllocationSize, true);
|
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(
|
public override void Close(
|
||||||
@ -908,6 +921,19 @@ namespace memfs
|
|||||||
return STATUS_SUCCESS;
|
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(
|
public override Int32 Rename(
|
||||||
Object FileNode0,
|
Object FileNode0,
|
||||||
Object FileDesc,
|
Object FileDesc,
|
||||||
@ -1305,45 +1331,6 @@ namespace memfs
|
|||||||
FileNode.FileInfo.EaSize = FileNode.FileInfo.EaSize + EaSizePlus - EaSizeMinus;
|
FileNode.FileInfo.EaSize = FileNode.FileInfo.EaSize + EaSizePlus - EaSizeMinus;
|
||||||
return STATUS_SUCCESS;
|
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 FileNodeMap FileNodeMap;
|
||||||
private UInt32 MaxFileNodes;
|
private UInt32 MaxFileNodes;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user