mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-22 08:23:05 -05:00
sys,dll,inc: implement new Delete design and POSIX semantics
This commit is contained in:
parent
3e66082f11
commit
19823d84de
@ -42,8 +42,8 @@ install:
|
|||||||
build_script:
|
build_script:
|
||||||
- appveyor AddMessage "Reboot complete" -Category Information
|
- appveyor AddMessage "Reboot complete" -Category Information
|
||||||
# build cygfuse
|
# build cygfuse
|
||||||
- C:\cygwin64\setup-x86_64.exe -qnNd -P cygport
|
#- C:\cygwin64\setup-x86_64.exe -qnNd -P cygport
|
||||||
- C:\cygwin64\bin\bash --login -c "make -C '%CD%\opt\cygfuse' dist"
|
#- C:\cygwin64\bin\bash --login -c "make -C '%CD%\opt\cygfuse' dist"
|
||||||
#- C:\cygwin\setup-x86.exe -qnNd -P cygport
|
#- C:\cygwin\setup-x86.exe -qnNd -P cygport
|
||||||
#- C:\cygwin\bin\bash --login -c "make -C '%CD%\opt\cygfuse' dist"
|
#- C:\cygwin\bin\bash --login -c "make -C '%CD%\opt\cygfuse' dist"
|
||||||
# build winfsp
|
# build winfsp
|
||||||
|
@ -204,7 +204,8 @@ enum
|
|||||||
UINT32 WslFeatures:1; /* support features required for WSLinux */\
|
UINT32 WslFeatures:1; /* support features required for WSLinux */\
|
||||||
UINT32 DirectoryMarkerAsNextOffset:1; /* directory marker is next offset instead of last name */\
|
UINT32 DirectoryMarkerAsNextOffset:1; /* directory marker is next offset instead of last name */\
|
||||||
UINT32 RejectIrpPriorToTransact0:1; /* reject IRP's prior to FspFsctlTransact with 0 buffers */\
|
UINT32 RejectIrpPriorToTransact0:1; /* reject IRP's prior to FspFsctlTransact with 0 buffers */\
|
||||||
UINT32 KmReservedFlags:3;\
|
UINT32 SupportsPosixUnlinkRename:1; /* file system supports POSIX-style unlink and rename */\
|
||||||
|
UINT32 KmReservedFlags:2;\
|
||||||
WCHAR Prefix[FSP_FSCTL_VOLUME_PREFIX_SIZE / sizeof(WCHAR)]; /* UNC prefix (\Server\Share) */\
|
WCHAR Prefix[FSP_FSCTL_VOLUME_PREFIX_SIZE / sizeof(WCHAR)]; /* UNC prefix (\Server\Share) */\
|
||||||
WCHAR FileSystemName[FSP_FSCTL_VOLUME_FSNAME_SIZE / sizeof(WCHAR)];
|
WCHAR FileSystemName[FSP_FSCTL_VOLUME_FSNAME_SIZE / sizeof(WCHAR)];
|
||||||
#define FSP_FSCTL_VOLUME_PARAMS_V1_FIELD_DEFN\
|
#define FSP_FSCTL_VOLUME_PARAMS_V1_FIELD_DEFN\
|
||||||
@ -413,6 +414,10 @@ typedef struct
|
|||||||
UINT32 Delete:1;
|
UINT32 Delete:1;
|
||||||
} Disposition;
|
} Disposition;
|
||||||
struct
|
struct
|
||||||
|
{
|
||||||
|
UINT32 Flags;
|
||||||
|
} DispositionEx;
|
||||||
|
struct
|
||||||
{
|
{
|
||||||
UINT64 FileSize;
|
UINT64 FileSize;
|
||||||
} EndOfFile;
|
} EndOfFile;
|
||||||
|
@ -47,6 +47,19 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The FILE_DISPOSITION_* definitions appear to be missing from the user mode headers.
|
||||||
|
*/
|
||||||
|
#if !defined(FILE_DISPOSITION_DELETE)
|
||||||
|
#define FILE_DISPOSITION_DO_NOT_DELETE 0x00000000
|
||||||
|
#define FILE_DISPOSITION_DELETE 0x00000001
|
||||||
|
#define FILE_DISPOSITION_POSIX_SEMANTICS 0x00000002
|
||||||
|
/* remaining flags are not needed for user mode file systems but included for completeness */
|
||||||
|
#define FILE_DISPOSITION_FORCE_IMAGE_SECTION_CHECK 0x00000004
|
||||||
|
#define FILE_DISPOSITION_ON_CLOSE 0x00000008
|
||||||
|
#define FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE 0x00000010
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The REPARSE_DATA_BUFFER definitions appear to be missing from the user mode headers.
|
* The REPARSE_DATA_BUFFER definitions appear to be missing from the user mode headers.
|
||||||
*/
|
*/
|
||||||
@ -348,6 +361,9 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
|
|||||||
/**
|
/**
|
||||||
* Cleanup a file.
|
* Cleanup a file.
|
||||||
*
|
*
|
||||||
|
* (NOTE: use of this function with the FspCleanupDelete flag is not recommended;
|
||||||
|
* use Delete instead.)
|
||||||
|
*
|
||||||
* 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
|
||||||
@ -402,6 +418,7 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
|
|||||||
* Close
|
* Close
|
||||||
* CanDelete
|
* CanDelete
|
||||||
* SetDelete
|
* SetDelete
|
||||||
|
* Delete
|
||||||
*/
|
*/
|
||||||
VOID (*Cleanup)(FSP_FILE_SYSTEM *FileSystem,
|
VOID (*Cleanup)(FSP_FILE_SYSTEM *FileSystem,
|
||||||
PVOID FileContext, PWSTR FileName, ULONG Flags);
|
PVOID FileContext, PWSTR FileName, ULONG Flags);
|
||||||
@ -575,6 +592,8 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
|
|||||||
/**
|
/**
|
||||||
* Determine whether a file or directory can be deleted.
|
* Determine whether a file or directory can be deleted.
|
||||||
*
|
*
|
||||||
|
* (NOTE: use of this function is not recommended; use Delete instead.)
|
||||||
|
*
|
||||||
* 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.
|
||||||
@ -599,6 +618,7 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
|
|||||||
* @see
|
* @see
|
||||||
* Cleanup
|
* Cleanup
|
||||||
* SetDelete
|
* SetDelete
|
||||||
|
* Delete
|
||||||
*/
|
*/
|
||||||
NTSTATUS (*CanDelete)(FSP_FILE_SYSTEM *FileSystem,
|
NTSTATUS (*CanDelete)(FSP_FILE_SYSTEM *FileSystem,
|
||||||
PVOID FileContext, PWSTR FileName);
|
PVOID FileContext, PWSTR FileName);
|
||||||
@ -880,6 +900,8 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
|
|||||||
/**
|
/**
|
||||||
* Set the file delete flag.
|
* Set the file delete flag.
|
||||||
*
|
*
|
||||||
|
* (NOTE: use of this function is not recommended; use Delete instead.)
|
||||||
|
*
|
||||||
* 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.
|
||||||
@ -908,6 +930,7 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
|
|||||||
* @see
|
* @see
|
||||||
* Cleanup
|
* Cleanup
|
||||||
* CanDelete
|
* CanDelete
|
||||||
|
* Delete
|
||||||
*/
|
*/
|
||||||
NTSTATUS (*SetDelete)(FSP_FILE_SYSTEM *FileSystem,
|
NTSTATUS (*SetDelete)(FSP_FILE_SYSTEM *FileSystem,
|
||||||
PVOID FileContext, PWSTR FileName, BOOLEAN DeleteFile);
|
PVOID FileContext, PWSTR FileName, BOOLEAN DeleteFile);
|
||||||
@ -1040,12 +1063,65 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
|
|||||||
PVOID FileContext,
|
PVOID FileContext,
|
||||||
PFILE_FULL_EA_INFORMATION Ea, ULONG EaLength,
|
PFILE_FULL_EA_INFORMATION Ea, ULONG EaLength,
|
||||||
FSP_FSCTL_FILE_INFO *FileInfo);
|
FSP_FSCTL_FILE_INFO *FileInfo);
|
||||||
|
/**
|
||||||
|
* Set the file delete flag or delete a file.
|
||||||
|
*
|
||||||
|
* This function replaces CanDelete, SetDelete and uses of Cleanup with the FspCleanupDelete flag
|
||||||
|
* and is recommended for use in all new code.
|
||||||
|
*
|
||||||
|
* 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:
|
||||||
|
* <ul>
|
||||||
|
* <li>FILE_DISPOSITION_DO_NOT_DELETE: Unmark the file for deletion.
|
||||||
|
* Do <b>NOT</b> delete the file either now or at Cleanup time.</li>
|
||||||
|
* <li>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.</li>
|
||||||
|
* <li>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 FSP_FSCTL_VOLUME_PARAMS :: SupportsPosixUnlinkRename is set.</li>
|
||||||
|
* <li>-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.</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* This function gets called in all file deletion scenarios:
|
||||||
|
* <ul>
|
||||||
|
* <li>When the DeleteFile or RemoveDirectory API's are used.</li>
|
||||||
|
* <li>When the SetInformationByHandle API with FileDispositionInfo or FileDispositionInfoEx is used.
|
||||||
|
* <li>When a file is opened using FILE_DELETE_ON_CLOSE.</li>
|
||||||
|
* <li>Etc.</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* NOTE: Delete takes precedence over CanDelete, SetDelete and Cleanup with the FspCleanupDelete flag.
|
||||||
|
* This means that if Delete is defined, CanDelete and SetDelete will never be called and
|
||||||
|
* Cleanup will never be called with the FspCleanupDelete flag.
|
||||||
|
*
|
||||||
|
* @param FileSystem
|
||||||
|
* The file system on which this request is posted.
|
||||||
|
* @param FileContext
|
||||||
|
* The file context of the file or directory to set the delete flag for.
|
||||||
|
* @param FileName
|
||||||
|
* The name of the file or directory to set the delete flag for.
|
||||||
|
* @param Flags
|
||||||
|
* File disposition flags
|
||||||
|
* @return
|
||||||
|
* STATUS_SUCCESS or error code.
|
||||||
|
* @see
|
||||||
|
* Cleanup
|
||||||
|
* CanDelete
|
||||||
|
* SetDelete
|
||||||
|
*/
|
||||||
|
NTSTATUS (*Delete)(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
PVOID FileContext, PWSTR FileName, ULONG Flags);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This ensures that this interface will always contain 64 function pointers.
|
* This ensures that this interface will always contain 64 function pointers.
|
||||||
* Please update when changing the interface as it is important for future compatibility.
|
* Please update when changing the interface as it is important for future compatibility.
|
||||||
*/
|
*/
|
||||||
NTSTATUS (*Reserved[33])();
|
NTSTATUS (*Reserved[32])();
|
||||||
} FSP_FILE_SYSTEM_INTERFACE;
|
} FSP_FILE_SYSTEM_INTERFACE;
|
||||||
FSP_FSCTL_STATIC_ASSERT(sizeof(FSP_FILE_SYSTEM_INTERFACE) == 64 * sizeof(NTSTATUS (*)()),
|
FSP_FSCTL_STATIC_ASSERT(sizeof(FSP_FILE_SYSTEM_INTERFACE) == 64 * sizeof(NTSTATUS (*)()),
|
||||||
"FSP_FILE_SYSTEM_INTERFACE must have 64 entries.");
|
"FSP_FILE_SYSTEM_INTERFACE must have 64 entries.");
|
||||||
|
@ -56,7 +56,10 @@ FSP_API NTSTATUS FspFileSystemOpEnter(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
(FspFsctlTransactCleanupKind == Request->Kind &&
|
(FspFsctlTransactCleanupKind == Request->Kind &&
|
||||||
Request->Req.Cleanup.Delete) ||
|
Request->Req.Cleanup.Delete) ||
|
||||||
(FspFsctlTransactSetInformationKind == Request->Kind &&
|
(FspFsctlTransactSetInformationKind == Request->Kind &&
|
||||||
10/*FileRenameInformation*/ == Request->Req.SetInformation.FileInformationClass) ||
|
(10/*FileRenameInformation*/ == Request->Req.SetInformation.FileInformationClass ||
|
||||||
|
65/*FileRenameInformationEx*/ == Request->Req.SetInformation.FileInformationClass ||
|
||||||
|
(64/*FileDispositionInformationEx*/ == Request->Req.SetInformation.FileInformationClass &&
|
||||||
|
3/*DELETE|POSIX_SEMANTICS*/ == (3 & Request->Req.SetInformation.Info.DispositionEx.Flags)))) ||
|
||||||
FspFsctlTransactSetVolumeInformationKind == Request->Kind ||
|
FspFsctlTransactSetVolumeInformationKind == Request->Kind ||
|
||||||
(FspFsctlTransactFlushBuffersKind == Request->Kind &&
|
(FspFsctlTransactFlushBuffersKind == Request->Kind &&
|
||||||
0 == Request->Req.FlushBuffers.UserContext &&
|
0 == Request->Req.FlushBuffers.UserContext &&
|
||||||
@ -67,7 +70,9 @@ FSP_API NTSTATUS FspFileSystemOpEnter(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
else
|
else
|
||||||
if (FspFsctlTransactCreateKind == Request->Kind ||
|
if (FspFsctlTransactCreateKind == Request->Kind ||
|
||||||
(FspFsctlTransactSetInformationKind == Request->Kind &&
|
(FspFsctlTransactSetInformationKind == Request->Kind &&
|
||||||
13/*FileDispositionInformation*/ == Request->Req.SetInformation.FileInformationClass) ||
|
(13/*FileDispositionInformation*/ == Request->Req.SetInformation.FileInformationClass ||
|
||||||
|
(64/*FileDispositionInformationEx*/ == Request->Req.SetInformation.FileInformationClass &&
|
||||||
|
3/*DELETE|POSIX_SEMANTICS*/ != (3 & Request->Req.SetInformation.Info.DispositionEx.Flags)))) ||
|
||||||
FspFsctlTransactQueryDirectoryKind == Request->Kind ||
|
FspFsctlTransactQueryDirectoryKind == Request->Kind ||
|
||||||
FspFsctlTransactQueryVolumeInformationKind == Request->Kind)
|
FspFsctlTransactQueryVolumeInformationKind == Request->Kind)
|
||||||
{
|
{
|
||||||
@ -95,7 +100,10 @@ FSP_API NTSTATUS FspFileSystemOpLeave(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
(FspFsctlTransactCleanupKind == Request->Kind &&
|
(FspFsctlTransactCleanupKind == Request->Kind &&
|
||||||
Request->Req.Cleanup.Delete) ||
|
Request->Req.Cleanup.Delete) ||
|
||||||
(FspFsctlTransactSetInformationKind == Request->Kind &&
|
(FspFsctlTransactSetInformationKind == Request->Kind &&
|
||||||
10/*FileRenameInformation*/ == Request->Req.SetInformation.FileInformationClass) ||
|
(10/*FileRenameInformation*/ == Request->Req.SetInformation.FileInformationClass ||
|
||||||
|
65/*FileRenameInformationEx*/ == Request->Req.SetInformation.FileInformationClass ||
|
||||||
|
(64/*FileDispositionInformationEx*/ == Request->Req.SetInformation.FileInformationClass &&
|
||||||
|
3/*DELETE|POSIX_SEMANTICS*/ == (3 & Request->Req.SetInformation.Info.DispositionEx.Flags)))) ||
|
||||||
FspFsctlTransactSetVolumeInformationKind == Request->Kind ||
|
FspFsctlTransactSetVolumeInformationKind == Request->Kind ||
|
||||||
(FspFsctlTransactFlushBuffersKind == Request->Kind &&
|
(FspFsctlTransactFlushBuffersKind == Request->Kind &&
|
||||||
0 == Request->Req.FlushBuffers.UserContext &&
|
0 == Request->Req.FlushBuffers.UserContext &&
|
||||||
@ -106,7 +114,9 @@ FSP_API NTSTATUS FspFileSystemOpLeave(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
else
|
else
|
||||||
if (FspFsctlTransactCreateKind == Request->Kind ||
|
if (FspFsctlTransactCreateKind == Request->Kind ||
|
||||||
(FspFsctlTransactSetInformationKind == Request->Kind &&
|
(FspFsctlTransactSetInformationKind == Request->Kind &&
|
||||||
13/*FileDispositionInformation*/ == Request->Req.SetInformation.FileInformationClass) ||
|
(13/*FileDispositionInformation*/ == Request->Req.SetInformation.FileInformationClass ||
|
||||||
|
(64/*FileDispositionInformationEx*/ == Request->Req.SetInformation.FileInformationClass &&
|
||||||
|
3/*DELETE|POSIX_SEMANTICS*/ != (3 & Request->Req.SetInformation.Info.DispositionEx.Flags)))) ||
|
||||||
FspFsctlTransactQueryDirectoryKind == Request->Kind ||
|
FspFsctlTransactQueryDirectoryKind == Request->Kind ||
|
||||||
FspFsctlTransactQueryVolumeInformationKind == Request->Kind)
|
FspFsctlTransactQueryVolumeInformationKind == Request->Kind)
|
||||||
{
|
{
|
||||||
@ -978,16 +988,28 @@ FSP_API NTSTATUS FspFileSystemOpOverwrite(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
FSP_API NTSTATUS FspFileSystemOpCleanup(FSP_FILE_SYSTEM *FileSystem,
|
FSP_API NTSTATUS FspFileSystemOpCleanup(FSP_FILE_SYSTEM *FileSystem,
|
||||||
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response)
|
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response)
|
||||||
{
|
{
|
||||||
|
ULONG CleanupFlags =
|
||||||
|
(0 != Request->Req.Cleanup.Delete ? FspCleanupDelete : 0) |
|
||||||
|
(0 != Request->Req.Cleanup.SetAllocationSize ? FspCleanupSetAllocationSize : 0) |
|
||||||
|
(0 != Request->Req.Cleanup.SetArchiveBit ? FspCleanupSetArchiveBit : 0) |
|
||||||
|
(0 != Request->Req.Cleanup.SetLastAccessTime ? FspCleanupSetLastAccessTime : 0) |
|
||||||
|
(0 != Request->Req.Cleanup.SetLastWriteTime ? FspCleanupSetLastWriteTime : 0) |
|
||||||
|
(0 != Request->Req.Cleanup.SetChangeTime ? FspCleanupSetChangeTime : 0);
|
||||||
|
|
||||||
|
if (Request->Req.Cleanup.Delete && 0 != FileSystem->Interface->Delete)
|
||||||
|
{
|
||||||
|
FileSystem->Interface->Delete(FileSystem,
|
||||||
|
(PVOID)ValOfFileContext(Request->Req.Cleanup),
|
||||||
|
0 != Request->FileName.Size ? (PWSTR)Request->Buffer : 0,
|
||||||
|
(ULONG)-1);
|
||||||
|
CleanupFlags &= ~FspCleanupDelete;
|
||||||
|
}
|
||||||
|
|
||||||
if (0 != FileSystem->Interface->Cleanup)
|
if (0 != FileSystem->Interface->Cleanup)
|
||||||
FileSystem->Interface->Cleanup(FileSystem,
|
FileSystem->Interface->Cleanup(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,
|
||||||
(0 != Request->Req.Cleanup.Delete ? FspCleanupDelete : 0) |
|
CleanupFlags);
|
||||||
(0 != Request->Req.Cleanup.SetAllocationSize ? FspCleanupSetAllocationSize : 0) |
|
|
||||||
(0 != Request->Req.Cleanup.SetArchiveBit ? FspCleanupSetArchiveBit : 0) |
|
|
||||||
(0 != Request->Req.Cleanup.SetLastAccessTime ? FspCleanupSetLastAccessTime : 0) |
|
|
||||||
(0 != Request->Req.Cleanup.SetLastWriteTime ? FspCleanupSetLastWriteTime : 0) |
|
|
||||||
(0 != Request->Req.Cleanup.SetChangeTime ? FspCleanupSetChangeTime : 0));
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -1134,7 +1156,9 @@ FSP_API NTSTATUS FspFileSystemOpSetInformation(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
&FileInfo);
|
&FileInfo);
|
||||||
break;
|
break;
|
||||||
case 13/*FileDispositionInformation*/:
|
case 13/*FileDispositionInformation*/:
|
||||||
if (0 != FileSystem->Interface->GetFileInfo)
|
case 64/*FileDispositionInformationEx*/:
|
||||||
|
if (0 == (0x10/*IGNORE_READONLY_ATTRIBUTE*/ & Request->Req.SetInformation.Info.DispositionEx.Flags) &&
|
||||||
|
0 != FileSystem->Interface->GetFileInfo)
|
||||||
{
|
{
|
||||||
Result = FileSystem->Interface->GetFileInfo(FileSystem,
|
Result = FileSystem->Interface->GetFileInfo(FileSystem,
|
||||||
(PVOID)ValOfFileContext(Request->Req.SetInformation), &FileInfo);
|
(PVOID)ValOfFileContext(Request->Req.SetInformation), &FileInfo);
|
||||||
@ -1144,7 +1168,17 @@ FSP_API NTSTATUS FspFileSystemOpSetInformation(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (0 != FileSystem->Interface->SetDelete)
|
if (0 != FileSystem->Interface->Delete)
|
||||||
|
{
|
||||||
|
Result = FileSystem->Interface->Delete(FileSystem,
|
||||||
|
(PVOID)ValOfFileContext(Request->Req.SetInformation),
|
||||||
|
(PWSTR)Request->Buffer,
|
||||||
|
Request->Req.SetInformation.Info.DispositionEx.Flags & 3/*DELETE|POSIX_SEMANTICS*/);
|
||||||
|
}
|
||||||
|
else if (0 != (2/*POSIX_SEMANTICS*/ & Request->Req.SetInformation.Info.DispositionEx.Flags))
|
||||||
|
/* only FSP_FILE_SYSTEM_INTERFACE::Delete can do POSIX semantics; return error if unimplemented */
|
||||||
|
Result = STATUS_INVALID_PARAMETER;
|
||||||
|
else if (0 != FileSystem->Interface->SetDelete)
|
||||||
{
|
{
|
||||||
Result = FileSystem->Interface->SetDelete(FileSystem,
|
Result = FileSystem->Interface->SetDelete(FileSystem,
|
||||||
(PVOID)ValOfFileContext(Request->Req.SetInformation),
|
(PVOID)ValOfFileContext(Request->Req.SetInformation),
|
||||||
@ -1162,6 +1196,7 @@ FSP_API NTSTATUS FspFileSystemOpSetInformation(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 10/*FileRenameInformation*/:
|
case 10/*FileRenameInformation*/:
|
||||||
|
case 65/*FileRenameInformationEx*/:
|
||||||
if (0 != FileSystem->Interface->Rename)
|
if (0 != FileSystem->Interface->Rename)
|
||||||
{
|
{
|
||||||
if (0 != Request->Req.SetInformation.Info.Rename.AccessToken)
|
if (0 != Request->Req.SetInformation.Info.Rename.AccessToken)
|
||||||
|
@ -82,21 +82,21 @@ static NTSTATUS FspFsvolCleanup(
|
|||||||
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
|
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
|
||||||
FSP_FSCTL_TRANSACT_REQ *Request;
|
FSP_FSCTL_TRANSACT_REQ *Request;
|
||||||
ULONG CleanupFlags;
|
ULONG CleanupFlags;
|
||||||
BOOLEAN DeletePending, SetAllocationSize, FileModified;
|
BOOLEAN Delete, SetAllocationSize, FileModified;
|
||||||
|
|
||||||
ASSERT(FileNode == FileDesc->FileNode);
|
ASSERT(FileNode == FileDesc->FileNode);
|
||||||
|
|
||||||
FspFileNodeAcquireExclusive(FileNode, Main);
|
FspFileNodeAcquireExclusive(FileNode, Main);
|
||||||
|
|
||||||
FspFileNodeCleanup(FileNode, FileObject, &CleanupFlags);
|
FspFileNodeCleanup(FileNode, FileObject, &CleanupFlags);
|
||||||
DeletePending = CleanupFlags & 1;
|
Delete = (CleanupFlags & 1) && !FileNode->PosixDelete;
|
||||||
SetAllocationSize = !!(CleanupFlags & 2);
|
SetAllocationSize = !!(CleanupFlags & 2);
|
||||||
FileModified = BooleanFlagOn(FileObject->Flags, FO_FILE_MODIFIED);
|
FileModified = BooleanFlagOn(FileObject->Flags, FO_FILE_MODIFIED);
|
||||||
|
|
||||||
/* if this is a directory inform the FSRTL Notify mechanism */
|
/* if this is a directory inform the FSRTL Notify mechanism */
|
||||||
if (FileNode->IsDirectory)
|
if (FileNode->IsDirectory)
|
||||||
{
|
{
|
||||||
if (DeletePending)
|
if (Delete)
|
||||||
FspNotifyDeletePending(
|
FspNotifyDeletePending(
|
||||||
FsvolDeviceExtension->NotifySync, &FsvolDeviceExtension->NotifyList, FileNode);
|
FsvolDeviceExtension->NotifySync, &FsvolDeviceExtension->NotifyList, FileNode);
|
||||||
|
|
||||||
@ -108,12 +108,12 @@ static NTSTATUS FspFsvolCleanup(
|
|||||||
FspFileNodeUnlockAll(FileNode, FileObject, IoGetRequestorProcess(Irp));
|
FspFileNodeUnlockAll(FileNode, FileObject, IoGetRequestorProcess(Irp));
|
||||||
|
|
||||||
/* create the user-mode file system request; MustSucceed because IRP_MJ_CLEANUP cannot fail */
|
/* create the user-mode file system request; MustSucceed because IRP_MJ_CLEANUP cannot fail */
|
||||||
FspIopCreateRequestMustSucceedEx(Irp, DeletePending ? &FileNode->FileName : 0, 0,
|
FspIopCreateRequestMustSucceedEx(Irp, Delete ? &FileNode->FileName : 0, 0,
|
||||||
FspFsvolCleanupRequestFini, &Request);
|
FspFsvolCleanupRequestFini, &Request);
|
||||||
Request->Kind = FspFsctlTransactCleanupKind;
|
Request->Kind = FspFsctlTransactCleanupKind;
|
||||||
Request->Req.Cleanup.UserContext = FileNode->UserContext;
|
Request->Req.Cleanup.UserContext = FileNode->UserContext;
|
||||||
Request->Req.Cleanup.UserContext2 = FileDesc->UserContext2;
|
Request->Req.Cleanup.UserContext2 = FileDesc->UserContext2;
|
||||||
Request->Req.Cleanup.Delete = DeletePending;
|
Request->Req.Cleanup.Delete = Delete;
|
||||||
Request->Req.Cleanup.SetAllocationSize = SetAllocationSize;
|
Request->Req.Cleanup.SetAllocationSize = SetAllocationSize;
|
||||||
Request->Req.Cleanup.SetArchiveBit = (FileModified || FileDesc->DidSetSecurity) &&
|
Request->Req.Cleanup.SetArchiveBit = (FileModified || FileDesc->DidSetSecurity) &&
|
||||||
!FileDesc->DidSetFileAttributes;
|
!FileDesc->DidSetFileAttributes;
|
||||||
@ -170,7 +170,12 @@ NTSTATUS FspFsvolCleanupComplete(
|
|||||||
ASSERT(FileNode == FileDesc->FileNode);
|
ASSERT(FileNode == FileDesc->FileNode);
|
||||||
|
|
||||||
/* send the appropriate notification; also invalidate dirinfo/etc. caches */
|
/* send the appropriate notification; also invalidate dirinfo/etc. caches */
|
||||||
if (Request->Req.Cleanup.Delete)
|
if (FileNode->PosixDelete)
|
||||||
|
{
|
||||||
|
NotifyFilter = 0;
|
||||||
|
NotifyAction = 0;
|
||||||
|
}
|
||||||
|
else if (Request->Req.Cleanup.Delete)
|
||||||
{
|
{
|
||||||
NotifyFilter = FileNode->IsDirectory ?
|
NotifyFilter = FileNode->IsDirectory ?
|
||||||
FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME;
|
FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME;
|
||||||
|
@ -1462,6 +1462,7 @@ typedef struct FSP_FILE_NODE
|
|||||||
ULONG EaChangeNumber;
|
ULONG EaChangeNumber;
|
||||||
ULONG EaChangeCount;
|
ULONG EaChangeCount;
|
||||||
BOOLEAN TruncateOnClose;
|
BOOLEAN TruncateOnClose;
|
||||||
|
BOOLEAN PosixDelete;
|
||||||
FILE_LOCK FileLock;
|
FILE_LOCK FileLock;
|
||||||
#if (NTDDI_VERSION < NTDDI_WIN8)
|
#if (NTDDI_VERSION < NTDDI_WIN8)
|
||||||
OPLOCK Oplock;
|
OPLOCK Oplock;
|
||||||
@ -1561,6 +1562,7 @@ NTSTATUS FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
|||||||
VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, PULONG PCleanupFlags);
|
VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, PULONG PCleanupFlags);
|
||||||
VOID FspFileNodeCleanupFlush(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject);
|
VOID FspFileNodeCleanupFlush(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject);
|
||||||
VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject);
|
VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject);
|
||||||
|
VOID FspFileNodePosixDelete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject);
|
||||||
VOID FspFileNodeClose(FSP_FILE_NODE *FileNode,
|
VOID FspFileNodeClose(FSP_FILE_NODE *FileNode,
|
||||||
PFILE_OBJECT FileObject, /* non-0 to remove share access */
|
PFILE_OBJECT FileObject, /* non-0 to remove share access */
|
||||||
BOOLEAN HandleCleanup); /* TRUE to decrement handle count */
|
BOOLEAN HandleCleanup); /* TRUE to decrement handle count */
|
||||||
|
@ -43,6 +43,7 @@ NTSTATUS FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
|||||||
VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, PULONG PCleanupFlags);
|
VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, PULONG PCleanupFlags);
|
||||||
VOID FspFileNodeCleanupFlush(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject);
|
VOID FspFileNodeCleanupFlush(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject);
|
||||||
VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject);
|
VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject);
|
||||||
|
VOID FspFileNodePosixDelete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject);
|
||||||
VOID FspFileNodeClose(FSP_FILE_NODE *FileNode,
|
VOID FspFileNodeClose(FSP_FILE_NODE *FileNode,
|
||||||
PFILE_OBJECT FileObject, /* non-0 to remove share access */
|
PFILE_OBJECT FileObject, /* non-0 to remove share access */
|
||||||
BOOLEAN HandleCleanup); /* TRUE to decrement handle count */
|
BOOLEAN HandleCleanup); /* TRUE to decrement handle count */
|
||||||
@ -141,6 +142,7 @@ VOID FspFileNodeOplockComplete(PVOID Context, PIRP Irp);
|
|||||||
#pragma alloc_text(PAGE, FspFileNodeCleanup)
|
#pragma alloc_text(PAGE, FspFileNodeCleanup)
|
||||||
#pragma alloc_text(PAGE, FspFileNodeCleanupFlush)
|
#pragma alloc_text(PAGE, FspFileNodeCleanupFlush)
|
||||||
#pragma alloc_text(PAGE, FspFileNodeCleanupComplete)
|
#pragma alloc_text(PAGE, FspFileNodeCleanupComplete)
|
||||||
|
#pragma alloc_text(PAGE, FspFileNodePosixDelete)
|
||||||
#pragma alloc_text(PAGE, FspFileNodeClose)
|
#pragma alloc_text(PAGE, FspFileNodeClose)
|
||||||
#pragma alloc_text(PAGE, FspFileNodeFlushAndPurgeCache)
|
#pragma alloc_text(PAGE, FspFileNodeFlushAndPurgeCache)
|
||||||
#pragma alloc_text(PAGE, FspFileNodeOverwriteStreams)
|
#pragma alloc_text(PAGE, FspFileNodeOverwriteStreams)
|
||||||
@ -909,7 +911,7 @@ VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject
|
|||||||
DeletePending = 0 != FileNode->DeletePending;
|
DeletePending = 0 != FileNode->DeletePending;
|
||||||
MemoryBarrier();
|
MemoryBarrier();
|
||||||
|
|
||||||
if (DeletePending)
|
if (DeletePending && !FileNode->PosixDelete)
|
||||||
{
|
{
|
||||||
FspFsvolDeviceDeleteContextByName(FsvolDeviceObject, &FileNode->FileName,
|
FspFsvolDeviceDeleteContextByName(FsvolDeviceObject, &FileNode->FileName,
|
||||||
&DeletedFromContextTable);
|
&DeletedFromContextTable);
|
||||||
@ -1013,6 +1015,66 @@ VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject
|
|||||||
FspFileNodeDereference(FileNode);
|
FspFileNodeDereference(FileNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID FspFileNodePosixDelete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Perform a POSIX delete of a FileNode. This removes the FileNode from the Context table.
|
||||||
|
*
|
||||||
|
* The FileNode must be acquired exclusive (Main or Full) when calling this function.
|
||||||
|
*/
|
||||||
|
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
PDEVICE_OBJECT FsvolDeviceObject = FileNode->FsvolDeviceObject;
|
||||||
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||||
|
BOOLEAN DeletedFromContextTable = FALSE;
|
||||||
|
|
||||||
|
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
|
||||||
|
|
||||||
|
FspFsvolDeviceDeleteContextByName(FsvolDeviceObject, &FileNode->FileName,
|
||||||
|
&DeletedFromContextTable);
|
||||||
|
ASSERT(DeletedFromContextTable);
|
||||||
|
|
||||||
|
FileNode->OpenCount = 0;
|
||||||
|
|
||||||
|
if (FsvolDeviceExtension->VolumeParams.NamedStreams &&
|
||||||
|
0 == FileNode->MainFileNode)
|
||||||
|
{
|
||||||
|
BOOLEAN StreamDeletedFromContextTable;
|
||||||
|
USHORT FileNameLength = FileNode->FileName.Length;
|
||||||
|
|
||||||
|
GATHER_DESCENDANTS(&FileNode->FileName, FALSE,
|
||||||
|
if (DescendantFileNode->FileName.Length > FileNameLength &&
|
||||||
|
L'\\' == DescendantFileNode->FileName.Buffer[FileNameLength / sizeof(WCHAR)])
|
||||||
|
break;
|
||||||
|
ASSERT(FileNode != DescendantFileNode);
|
||||||
|
ASSERT(0 != DescendantFileNode->OpenCount);
|
||||||
|
);
|
||||||
|
|
||||||
|
for (
|
||||||
|
DescendantFileNodeIndex = 0;
|
||||||
|
DescendantFileNodeCount > DescendantFileNodeIndex;
|
||||||
|
DescendantFileNodeIndex++)
|
||||||
|
{
|
||||||
|
DescendantFileNode = DescendantFileNodes[DescendantFileNodeIndex];
|
||||||
|
|
||||||
|
FspFsvolDeviceDeleteContextByName(FsvolDeviceObject, &DescendantFileNode->FileName,
|
||||||
|
&StreamDeletedFromContextTable);
|
||||||
|
if (StreamDeletedFromContextTable)
|
||||||
|
{
|
||||||
|
DescendantFileNode->OpenCount = 0;
|
||||||
|
FspFileNodeDereference(DescendantFileNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SCATTER_DESCENDANTS(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
FspFsvolDeviceUnlockContextTable(FsvolDeviceObject);
|
||||||
|
|
||||||
|
FspFileNodeDereference(FileNode);
|
||||||
|
}
|
||||||
|
|
||||||
VOID FspFileNodeClose(FSP_FILE_NODE *FileNode,
|
VOID FspFileNodeClose(FSP_FILE_NODE *FileNode,
|
||||||
PFILE_OBJECT FileObject, /* non-0 to remove share access */
|
PFILE_OBJECT FileObject, /* non-0 to remove share access */
|
||||||
BOOLEAN HandleCleanup) /* TRUE to decrement handle count */
|
BOOLEAN HandleCleanup) /* TRUE to decrement handle count */
|
||||||
|
@ -1441,7 +1441,8 @@ static NTSTATUS FspFsvolSetDispositionInformation(
|
|||||||
|
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||||
PFILE_DISPOSITION_INFORMATION Info = (PFILE_DISPOSITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
|
FILE_INFORMATION_CLASS FileInformationClass = IrpSp->Parameters.SetFile.FileInformationClass;
|
||||||
|
UINT32 DispositionFlags;
|
||||||
ULONG Length = IrpSp->Parameters.SetFile.Length;
|
ULONG Length = IrpSp->Parameters.SetFile.Length;
|
||||||
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||||
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
|
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
|
||||||
@ -1449,9 +1450,34 @@ static NTSTATUS FspFsvolSetDispositionInformation(
|
|||||||
BOOLEAN Success;
|
BOOLEAN Success;
|
||||||
|
|
||||||
ASSERT(FileNode == FileDesc->FileNode);
|
ASSERT(FileNode == FileDesc->FileNode);
|
||||||
|
ASSERT(
|
||||||
|
FileDispositionInformation == FileInformationClass ||
|
||||||
|
FileDispositionInformationEx == FileInformationClass);
|
||||||
|
|
||||||
|
if (FileDispositionInformation == FileInformationClass)
|
||||||
|
{
|
||||||
|
if (sizeof(FILE_DISPOSITION_INFORMATION) > Length)
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
DispositionFlags = !!((PFILE_DISPOSITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer)->DeleteFile;
|
||||||
|
DispositionFlags |= FILE_DISPOSITION_FORCE_IMAGE_SECTION_CHECK;
|
||||||
|
// old-school delete always did image section check; see below
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!FspFsvolDeviceExtension(FsvolDeviceObject)->VolumeParams.SupportsPosixUnlinkRename)
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
if (sizeof(FILE_DISPOSITION_INFORMATION_EX) > Length)
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
DispositionFlags = ((PFILE_DISPOSITION_INFORMATION_EX)Irp->AssociatedIrp.SystemBuffer)->Flags;
|
||||||
|
|
||||||
|
/* !!!: REVISIT:
|
||||||
|
* For now we cannot handle the FILE_DISPOSITION_ON_CLOSE flag,
|
||||||
|
* as we need to understand the semantics better.
|
||||||
|
*/
|
||||||
|
if (FlagOn(DispositionFlags, FILE_DISPOSITION_ON_CLOSE))
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
if (sizeof(FILE_DISPOSITION_INFORMATION) > Length)
|
|
||||||
return STATUS_INVALID_PARAMETER;
|
|
||||||
if (FileNode->IsRootDirectory)
|
if (FileNode->IsRootDirectory)
|
||||||
/* cannot delete root directory */
|
/* cannot delete root directory */
|
||||||
return STATUS_CANNOT_DELETE;
|
return STATUS_CANNOT_DELETE;
|
||||||
@ -1459,7 +1485,7 @@ static NTSTATUS FspFsvolSetDispositionInformation(
|
|||||||
retry:
|
retry:
|
||||||
FspFileNodeAcquireExclusive(FileNode, Full);
|
FspFileNodeAcquireExclusive(FileNode, Full);
|
||||||
|
|
||||||
if (Info->DeleteFile)
|
if (FlagOn(DispositionFlags, FILE_DISPOSITION_DELETE))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Perform oplock check.
|
* Perform oplock check.
|
||||||
@ -1487,15 +1513,40 @@ retry:
|
|||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
goto unlock_exit;
|
goto unlock_exit;
|
||||||
|
|
||||||
/* make sure no process is mapping the file as an image */
|
if (FlagOn(DispositionFlags, FILE_DISPOSITION_FORCE_IMAGE_SECTION_CHECK))
|
||||||
Success = MmFlushImageSection(FileObject->SectionObjectPointer, MmFlushForDelete);
|
|
||||||
if (!Success)
|
|
||||||
{
|
{
|
||||||
Result = STATUS_CANNOT_DELETE;
|
/* make sure no process is mapping the file as an image */
|
||||||
goto unlock_exit;
|
Success = MmFlushImageSection(FileObject->SectionObjectPointer, MmFlushForDelete);
|
||||||
|
if (!Success)
|
||||||
|
{
|
||||||
|
Result = STATUS_CANNOT_DELETE;
|
||||||
|
goto unlock_exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FlagOn(DispositionFlags, FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE))
|
||||||
|
{
|
||||||
|
/* if FileDesc does not have FILE_WRITE_ATTRIBUTE access, remove IGNORE_READONLY_ATTRIBUTE */
|
||||||
|
if (!FlagOn(FileDesc->GrantedAccess, FILE_WRITE_ATTRIBUTES))
|
||||||
|
DispositionFlags &= ~FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (FileNode->PosixDelete)
|
||||||
|
{
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
goto unlock_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FlagOn(DispositionFlags, FILE_DISPOSITION_DELETE))
|
||||||
|
DispositionFlags &=
|
||||||
|
FILE_DISPOSITION_DO_NOT_DELETE |
|
||||||
|
FILE_DISPOSITION_DELETE |
|
||||||
|
FILE_DISPOSITION_POSIX_SEMANTICS |
|
||||||
|
FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE;
|
||||||
|
else
|
||||||
|
DispositionFlags = FILE_DISPOSITION_DO_NOT_DELETE;
|
||||||
|
|
||||||
Result = FspIopCreateRequestEx(Irp, &FileNode->FileName, 0,
|
Result = FspIopCreateRequestEx(Irp, &FileNode->FileName, 0,
|
||||||
FspFsvolSetInformationRequestFini, &Request);
|
FspFsvolSetInformationRequestFini, &Request);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
@ -1504,8 +1555,8 @@ retry:
|
|||||||
Request->Kind = FspFsctlTransactSetInformationKind;
|
Request->Kind = FspFsctlTransactSetInformationKind;
|
||||||
Request->Req.SetInformation.UserContext = FileNode->UserContext;
|
Request->Req.SetInformation.UserContext = FileNode->UserContext;
|
||||||
Request->Req.SetInformation.UserContext2 = FileDesc->UserContext2;
|
Request->Req.SetInformation.UserContext2 = FileDesc->UserContext2;
|
||||||
Request->Req.SetInformation.FileInformationClass = FileDispositionInformation;
|
Request->Req.SetInformation.FileInformationClass = FileInformationClass;
|
||||||
Request->Req.SetInformation.Info.Disposition.Delete = Info->DeleteFile;
|
Request->Req.SetInformation.Info.DispositionEx.Flags = DispositionFlags;
|
||||||
|
|
||||||
FspFileNodeSetOwner(FileNode, Full, Request);
|
FspFileNodeSetOwner(FileNode, Full, Request);
|
||||||
FspIopRequestContext(Request, RequestFileNode) = FileNode;
|
FspIopRequestContext(Request, RequestFileNode) = FileNode;
|
||||||
@ -1525,23 +1576,51 @@ static NTSTATUS FspFsvolSetDispositionInformationSuccess(
|
|||||||
|
|
||||||
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||||
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||||
PFILE_DISPOSITION_INFORMATION Info = (PFILE_DISPOSITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
|
|
||||||
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||||
FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp);
|
FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp);
|
||||||
|
UINT32 DispositionFlags = Request->Req.SetInformation.Info.DispositionEx.Flags;
|
||||||
|
BOOLEAN DeleteFile = BooleanFlagOn(DispositionFlags, FILE_DISPOSITION_DELETE);
|
||||||
|
|
||||||
FileNode->DeletePending = Info->DeleteFile;
|
FileNode->DeletePending = DeleteFile;
|
||||||
FileObject->DeletePending = Info->DeleteFile;
|
FileObject->DeletePending = DeleteFile;
|
||||||
|
|
||||||
/* fastfat does this, although it seems unnecessary */
|
if (FlagOn(DispositionFlags, FILE_DISPOSITION_POSIX_SEMANTICS))
|
||||||
#if 1
|
|
||||||
if (FileNode->IsDirectory && Info->DeleteFile)
|
|
||||||
{
|
{
|
||||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
|
ASSERT(DeleteFile);
|
||||||
FspFsvolDeviceExtension(IrpSp->DeviceObject);
|
|
||||||
FspNotifyDeletePending(
|
FileNode->PosixDelete = TRUE;
|
||||||
FsvolDeviceExtension->NotifySync, &FsvolDeviceExtension->NotifyList, FileNode);
|
|
||||||
|
if (FileNode->IsDirectory)
|
||||||
|
{
|
||||||
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
|
||||||
|
FspFsvolDeviceExtension(IrpSp->DeviceObject);
|
||||||
|
FspNotifyDeletePending(
|
||||||
|
FsvolDeviceExtension->NotifySync, &FsvolDeviceExtension->NotifyList, FileNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* send the appropriate notification; also invalidate dirinfo/etc. caches */
|
||||||
|
ULONG NotifyFilter, NotifyAction;
|
||||||
|
NotifyFilter = FileNode->IsDirectory ?
|
||||||
|
FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME;
|
||||||
|
NotifyAction = FILE_ACTION_REMOVED;
|
||||||
|
FspFileNodeNotifyChange(FileNode, NotifyFilter, NotifyAction, TRUE);
|
||||||
|
|
||||||
|
/* perform POSIX delete: remove file node from the context table */
|
||||||
|
FspFileNodePosixDelete(FileNode, FileObject);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* fastfat does this, although it seems unnecessary */
|
||||||
|
#if 1
|
||||||
|
if (FileNode->IsDirectory && DeleteFile)
|
||||||
|
{
|
||||||
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
|
||||||
|
FspFsvolDeviceExtension(IrpSp->DeviceObject);
|
||||||
|
FspNotifyDeletePending(
|
||||||
|
FsvolDeviceExtension->NotifySync, &FsvolDeviceExtension->NotifyList, FileNode);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
FspIopRequestContext(Request, RequestFileNode) = 0;
|
FspIopRequestContext(Request, RequestFileNode) = 0;
|
||||||
FspFileNodeReleaseOwner(FileNode, Full, Request);
|
FspFileNodeReleaseOwner(FileNode, Full, Request);
|
||||||
@ -1796,10 +1875,15 @@ static NTSTATUS FspFsvolSetInformation(
|
|||||||
FILE_INFORMATION_CLASS FileInformationClass = IrpSp->Parameters.SetFile.FileInformationClass;
|
FILE_INFORMATION_CLASS FileInformationClass = IrpSp->Parameters.SetFile.FileInformationClass;
|
||||||
|
|
||||||
/* special case FileDispositionInformation/FileRenameInformation */
|
/* special case FileDispositionInformation/FileRenameInformation */
|
||||||
if (FileDispositionInformation == FileInformationClass)
|
switch (FileInformationClass)
|
||||||
|
{
|
||||||
|
case FileDispositionInformation:
|
||||||
|
case FileDispositionInformationEx:
|
||||||
return FspFsvolSetDispositionInformation(FsvolDeviceObject, Irp, IrpSp);
|
return FspFsvolSetDispositionInformation(FsvolDeviceObject, Irp, IrpSp);
|
||||||
if (FileRenameInformation == FileInformationClass)
|
case FileRenameInformation:
|
||||||
|
//case FileRenameInformationEx:
|
||||||
return FspFsvolSetRenameInformation(FsvolDeviceObject, Irp, IrpSp);
|
return FspFsvolSetRenameInformation(FsvolDeviceObject, Irp, IrpSp);
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||||
@ -1997,10 +2081,15 @@ NTSTATUS FspFsvolSetInformationComplete(
|
|||||||
FILE_INFORMATION_CLASS FileInformationClass = IrpSp->Parameters.SetFile.FileInformationClass;
|
FILE_INFORMATION_CLASS FileInformationClass = IrpSp->Parameters.SetFile.FileInformationClass;
|
||||||
|
|
||||||
/* special case FileDispositionInformation/FileRenameInformation */
|
/* special case FileDispositionInformation/FileRenameInformation */
|
||||||
if (FileDispositionInformation == FileInformationClass)
|
switch (FileInformationClass)
|
||||||
|
{
|
||||||
|
case FileDispositionInformation:
|
||||||
|
case FileDispositionInformationEx:
|
||||||
FSP_RETURN(Result = FspFsvolSetDispositionInformationSuccess(Irp, Response));
|
FSP_RETURN(Result = FspFsvolSetDispositionInformationSuccess(Irp, Response));
|
||||||
if (FileRenameInformation == FileInformationClass)
|
case FileRenameInformation:
|
||||||
|
//case FileRenameInformationEx:
|
||||||
FSP_RETURN(Result = FspFsvolSetRenameInformationSuccess(Irp, Response));
|
FSP_RETURN(Result = FspFsvolSetRenameInformationSuccess(Irp, Response));
|
||||||
|
}
|
||||||
|
|
||||||
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||||
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||||
|
@ -101,7 +101,8 @@ static NTSTATUS FspFsvolQueryFsAttributeInformation(
|
|||||||
(FsvolDeviceExtension->VolumeParams.NamedStreams ? FILE_NAMED_STREAMS : 0) |
|
(FsvolDeviceExtension->VolumeParams.NamedStreams ? FILE_NAMED_STREAMS : 0) |
|
||||||
//(FsvolDeviceExtension->VolumeParams.HardLinks ? FILE_SUPPORTS_HARD_LINKS : 0) |
|
//(FsvolDeviceExtension->VolumeParams.HardLinks ? FILE_SUPPORTS_HARD_LINKS : 0) |
|
||||||
(FsvolDeviceExtension->VolumeParams.ExtendedAttributes ? FILE_SUPPORTS_EXTENDED_ATTRIBUTES : 0) |
|
(FsvolDeviceExtension->VolumeParams.ExtendedAttributes ? FILE_SUPPORTS_EXTENDED_ATTRIBUTES : 0) |
|
||||||
(FsvolDeviceExtension->VolumeParams.ReadOnlyVolume ? FILE_READ_ONLY_VOLUME : 0);
|
(FsvolDeviceExtension->VolumeParams.ReadOnlyVolume ? FILE_READ_ONLY_VOLUME : 0) |
|
||||||
|
(FsvolDeviceExtension->VolumeParams.SupportsPosixUnlinkRename ? FILE_SUPPORTS_POSIX_UNLINK_RENAME : 0);
|
||||||
Info->MaximumComponentNameLength = FsvolDeviceExtension->VolumeParams.MaxComponentLength;
|
Info->MaximumComponentNameLength = FsvolDeviceExtension->VolumeParams.MaxComponentLength;
|
||||||
|
|
||||||
RtlInitUnicodeString(&FileSystemName, FsvolDeviceExtension->VolumeParams.FileSystemName);
|
RtlInitUnicodeString(&FileSystemName, FsvolDeviceExtension->VolumeParams.FileSystemName);
|
||||||
|
@ -32,6 +32,7 @@ set dfl_tests=^
|
|||||||
winfsp-tests-x64 ^
|
winfsp-tests-x64 ^
|
||||||
winfsp-tests-x64-case-randomize ^
|
winfsp-tests-x64-case-randomize ^
|
||||||
winfsp-tests-x64-flushpurge ^
|
winfsp-tests-x64-flushpurge ^
|
||||||
|
winfsp-tests-x64-legacy-unlink-rename ^
|
||||||
winfsp-tests-x64-mountpoint-drive ^
|
winfsp-tests-x64-mountpoint-drive ^
|
||||||
winfsp-tests-x64-mountpoint-dir ^
|
winfsp-tests-x64-mountpoint-dir ^
|
||||||
winfsp-tests-x64-mountpoint-dir-case-sensitive ^
|
winfsp-tests-x64-mountpoint-dir-case-sensitive ^
|
||||||
@ -52,6 +53,7 @@ set dfl_tests=^
|
|||||||
winfsp-tests-x86 ^
|
winfsp-tests-x86 ^
|
||||||
winfsp-tests-x86-case-randomize ^
|
winfsp-tests-x86-case-randomize ^
|
||||||
winfsp-tests-x86-flushpurge ^
|
winfsp-tests-x86-flushpurge ^
|
||||||
|
winfsp-tests-x86-legacy-unlink-rename ^
|
||||||
winfsp-tests-x86-mountpoint-drive ^
|
winfsp-tests-x86-mountpoint-drive ^
|
||||||
winfsp-tests-x86-mountpoint-dir ^
|
winfsp-tests-x86-mountpoint-dir ^
|
||||||
winfsp-tests-x86-mountpoint-dir-case-sensitive ^
|
winfsp-tests-x86-mountpoint-dir-case-sensitive ^
|
||||||
@ -191,6 +193,11 @@ winfsp-tests-x64 --flush-and-purge-on-cleanup * +ea*
|
|||||||
if !ERRORLEVEL! neq 0 goto fail
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
exit /b 0
|
exit /b 0
|
||||||
|
|
||||||
|
:winfsp-tests-x64-legacy-unlink-rename
|
||||||
|
winfsp-tests-x64 --legacy-unlink-rename * +ea*
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
:winfsp-tests-x64-mountpoint-drive
|
:winfsp-tests-x64-mountpoint-drive
|
||||||
winfsp-tests-x64 --mountpoint=X: --resilient * +ea*
|
winfsp-tests-x64 --mountpoint=X: --resilient * +ea*
|
||||||
if !ERRORLEVEL! neq 0 goto fail
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
@ -236,6 +243,11 @@ winfsp-tests-x86 --flush-and-purge-on-cleanup * +ea*
|
|||||||
if !ERRORLEVEL! neq 0 goto fail
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
exit /b 0
|
exit /b 0
|
||||||
|
|
||||||
|
:winfsp-tests-x86-legacy-unlink-rename
|
||||||
|
winfsp-tests-x86 --legacy-unlink-rename * +ea*
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
:winfsp-tests-x86-mountpoint-drive
|
:winfsp-tests-x86-mountpoint-drive
|
||||||
winfsp-tests-x86 --mountpoint=X: --resilient * +ea*
|
winfsp-tests-x86 --mountpoint=X: --resilient * +ea*
|
||||||
if !ERRORLEVEL! neq 0 goto fail
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
@ -88,6 +88,13 @@ FSP_FSCTL_STATIC_ASSERT(MEMFS_MAX_PATH > MAX_PATH,
|
|||||||
#define MEMFS_REJECT_EARLY_IRP
|
#define MEMFS_REJECT_EARLY_IRP
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define the MEMFS_DELETE macro to include new Delete support
|
||||||
|
* (instead of Cleanup/FspCleanupDelete). This is required to
|
||||||
|
* properly support POSIX unlink/rename.
|
||||||
|
*/
|
||||||
|
#define MEMFS_DELETE
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Define the DEBUG_BUFFER_CHECK macro on Windows 8 or above. This includes
|
* Define the DEBUG_BUFFER_CHECK macro on Windows 8 or above. This includes
|
||||||
* a check for the Write buffer to ensure that it is read-only.
|
* a check for the Write buffer to ensure that it is read-only.
|
||||||
@ -965,6 +972,8 @@ void SlowioReadDirectoryThread(
|
|||||||
* FSP_FILE_SYSTEM_INTERFACE
|
* FSP_FILE_SYSTEM_INTERFACE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static NTSTATUS Delete(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
PVOID FileNode0, PWSTR FileName, ULONG Flags);
|
||||||
#if defined(MEMFS_REPARSE_POINTS)
|
#if defined(MEMFS_REPARSE_POINTS)
|
||||||
static NTSTATUS GetReparsePointByName(
|
static NTSTATUS GetReparsePointByName(
|
||||||
FSP_FILE_SYSTEM *FileSystem, PVOID Context,
|
FSP_FILE_SYSTEM *FileSystem, PVOID Context,
|
||||||
@ -1347,7 +1356,9 @@ static VOID Cleanup(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
MEMFS_FILE_NODE *MainFileNode = FileNode;
|
MEMFS_FILE_NODE *MainFileNode = FileNode;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !defined(MEMFS_DELETE)
|
||||||
assert(0 != Flags); /* FSP_FSCTL_VOLUME_PARAMS::PostCleanupWhenModifiedOnly ensures this */
|
assert(0 != Flags); /* FSP_FSCTL_VOLUME_PARAMS::PostCleanupWhenModifiedOnly ensures this */
|
||||||
|
#endif
|
||||||
|
|
||||||
if (Flags & FspCleanupSetArchiveBit)
|
if (Flags & FspCleanupSetArchiveBit)
|
||||||
{
|
{
|
||||||
@ -1376,21 +1387,10 @@ static VOID Cleanup(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
SetFileSizeInternal(FileSystem, FileNode, AllocationSize, TRUE);
|
SetFileSizeInternal(FileSystem, FileNode, AllocationSize, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((Flags & FspCleanupDelete) && !MemfsFileNodeMapHasChild(Memfs->FileNodeMap, FileNode))
|
#if !defined(MEMFS_DELETE)
|
||||||
{
|
if (Flags & FspCleanupDelete)
|
||||||
#if defined(MEMFS_NAMED_STREAMS)
|
Delete(FileSystem, FileNode0, FileName, -1);
|
||||||
MEMFS_FILE_NODE_MAP_ENUM_CONTEXT Context = { FALSE };
|
|
||||||
ULONG Index;
|
|
||||||
|
|
||||||
MemfsFileNodeMapEnumerateNamedStreams(Memfs->FileNodeMap, FileNode,
|
|
||||||
MemfsFileNodeMapEnumerateFn, &Context);
|
|
||||||
for (Index = 0; Context.Count > Index; Index++)
|
|
||||||
MemfsFileNodeMapRemove(Memfs->FileNodeMap, Context.FileNodes[Index]);
|
|
||||||
MemfsFileNodeMapEnumerateFree(&Context);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
MemfsFileNodeMapRemove(Memfs->FileNodeMap, FileNode);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static VOID Close(FSP_FILE_SYSTEM *FileSystem,
|
static VOID Close(FSP_FILE_SYSTEM *FileSystem,
|
||||||
@ -1651,17 +1651,13 @@ static NTSTATUS SetFileSize(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined(MEMFS_DELETE)
|
||||||
static NTSTATUS CanDelete(FSP_FILE_SYSTEM *FileSystem,
|
static NTSTATUS CanDelete(FSP_FILE_SYSTEM *FileSystem,
|
||||||
PVOID FileNode0, PWSTR FileName)
|
PVOID FileNode0, PWSTR FileName)
|
||||||
{
|
{
|
||||||
MEMFS *Memfs = (MEMFS *)FileSystem->UserContext;
|
return Delete(FileSystem, FileNode0, FileName, FILE_DISPOSITION_DELETE);
|
||||||
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0;
|
|
||||||
|
|
||||||
if (MemfsFileNodeMapHasChild(Memfs->FileNodeMap, FileNode))
|
|
||||||
return STATUS_DIRECTORY_NOT_EMPTY;
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static NTSTATUS Rename(FSP_FILE_SYSTEM *FileSystem,
|
static NTSTATUS Rename(FSP_FILE_SYSTEM *FileSystem,
|
||||||
PVOID FileNode0,
|
PVOID FileNode0,
|
||||||
@ -2231,6 +2227,54 @@ static NTSTATUS SetEa(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static NTSTATUS Delete(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
PVOID FileNode0, PWSTR FileName, ULONG Flags)
|
||||||
|
{
|
||||||
|
MEMFS *Memfs = (MEMFS *)FileSystem->UserContext;
|
||||||
|
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0;
|
||||||
|
|
||||||
|
switch (Flags)
|
||||||
|
{
|
||||||
|
case FILE_DISPOSITION_DO_NOT_DELETE:
|
||||||
|
// set file disposition flag: do not delete file at Cleanup
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
|
||||||
|
case FILE_DISPOSITION_DELETE:
|
||||||
|
// set file disposition flag: delete file at Cleanup
|
||||||
|
if (MemfsFileNodeMapHasChild(Memfs->FileNodeMap, FileNode))
|
||||||
|
return STATUS_DIRECTORY_NOT_EMPTY;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
|
||||||
|
case FILE_DISPOSITION_DELETE | FILE_DISPOSITION_POSIX_SEMANTICS:
|
||||||
|
// delete file now; open handles to file remain valid
|
||||||
|
/* fallthrough */
|
||||||
|
|
||||||
|
case -1:
|
||||||
|
// delete file now; called during Cleanup
|
||||||
|
if (MemfsFileNodeMapHasChild(Memfs->FileNodeMap, FileNode))
|
||||||
|
return STATUS_DIRECTORY_NOT_EMPTY;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#if defined(MEMFS_NAMED_STREAMS)
|
||||||
|
MEMFS_FILE_NODE_MAP_ENUM_CONTEXT Context = { FALSE };
|
||||||
|
ULONG Index;
|
||||||
|
|
||||||
|
MemfsFileNodeMapEnumerateNamedStreams(Memfs->FileNodeMap, FileNode,
|
||||||
|
MemfsFileNodeMapEnumerateFn, &Context);
|
||||||
|
for (Index = 0; Context.Count > Index; Index++)
|
||||||
|
MemfsFileNodeMapRemove(Memfs->FileNodeMap, Context.FileNodes[Index]);
|
||||||
|
MemfsFileNodeMapEnumerateFree(&Context);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
MemfsFileNodeMapRemove(Memfs->FileNodeMap, FileNode);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static FSP_FILE_SYSTEM_INTERFACE MemfsInterface =
|
static FSP_FILE_SYSTEM_INTERFACE MemfsInterface =
|
||||||
{
|
{
|
||||||
GetVolumeInfo,
|
GetVolumeInfo,
|
||||||
@ -2255,7 +2299,11 @@ static FSP_FILE_SYSTEM_INTERFACE MemfsInterface =
|
|||||||
GetFileInfo,
|
GetFileInfo,
|
||||||
SetBasicInfo,
|
SetBasicInfo,
|
||||||
SetFileSize,
|
SetFileSize,
|
||||||
|
#if !defined(MEMFS_DELETE)
|
||||||
CanDelete,
|
CanDelete,
|
||||||
|
#else
|
||||||
|
0,
|
||||||
|
#endif
|
||||||
Rename,
|
Rename,
|
||||||
GetSecurity,
|
GetSecurity,
|
||||||
SetSecurity,
|
SetSecurity,
|
||||||
@ -2293,11 +2341,15 @@ static FSP_FILE_SYSTEM_INTERFACE MemfsInterface =
|
|||||||
#if defined(MEMFS_EA)
|
#if defined(MEMFS_EA)
|
||||||
Overwrite,
|
Overwrite,
|
||||||
GetEa,
|
GetEa,
|
||||||
SetEa
|
SetEa,
|
||||||
#else
|
#else
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
|
#endif
|
||||||
|
#if defined(MEMFS_DELETE)
|
||||||
|
Delete,
|
||||||
|
#else
|
||||||
0,
|
0,
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
@ -2323,6 +2375,7 @@ NTSTATUS MemfsCreateFunnel(
|
|||||||
FSP_FSCTL_VOLUME_PARAMS VolumeParams;
|
FSP_FSCTL_VOLUME_PARAMS VolumeParams;
|
||||||
BOOLEAN CaseInsensitive = !!(Flags & MemfsCaseInsensitive);
|
BOOLEAN CaseInsensitive = !!(Flags & MemfsCaseInsensitive);
|
||||||
BOOLEAN FlushAndPurgeOnCleanup = !!(Flags & MemfsFlushAndPurgeOnCleanup);
|
BOOLEAN FlushAndPurgeOnCleanup = !!(Flags & MemfsFlushAndPurgeOnCleanup);
|
||||||
|
BOOLEAN SupportsPosixUnlinkRename = !(Flags & MemfsLegacyUnlinkRename);
|
||||||
PWSTR DevicePath = MemfsNet == (Flags & MemfsDeviceMask) ?
|
PWSTR DevicePath = MemfsNet == (Flags & MemfsDeviceMask) ?
|
||||||
L"" FSP_FSCTL_NET_DEVICE_NAME : L"" FSP_FSCTL_DISK_DEVICE_NAME;
|
L"" FSP_FSCTL_NET_DEVICE_NAME : L"" FSP_FSCTL_DISK_DEVICE_NAME;
|
||||||
UINT64 AllocationUnit;
|
UINT64 AllocationUnit;
|
||||||
@ -2404,6 +2457,7 @@ NTSTATUS MemfsCreateFunnel(
|
|||||||
#if defined(MEMFS_REJECT_EARLY_IRP)
|
#if defined(MEMFS_REJECT_EARLY_IRP)
|
||||||
VolumeParams.RejectIrpPriorToTransact0 = 1;
|
VolumeParams.RejectIrpPriorToTransact0 = 1;
|
||||||
#endif
|
#endif
|
||||||
|
VolumeParams.SupportsPosixUnlinkRename = SupportsPosixUnlinkRename;
|
||||||
if (0 != VolumePrefix)
|
if (0 != VolumePrefix)
|
||||||
wcscpy_s(VolumeParams.Prefix, sizeof VolumeParams.Prefix / sizeof(WCHAR), VolumePrefix);
|
wcscpy_s(VolumeParams.Prefix, sizeof VolumeParams.Prefix / sizeof(WCHAR), VolumePrefix);
|
||||||
wcscpy_s(VolumeParams.FileSystemName, sizeof VolumeParams.FileSystemName / sizeof(WCHAR),
|
wcscpy_s(VolumeParams.FileSystemName, sizeof VolumeParams.FileSystemName / sizeof(WCHAR),
|
||||||
|
@ -37,9 +37,10 @@ enum
|
|||||||
MemfsDeviceMask = 0x0000000f,
|
MemfsDeviceMask = 0x0000000f,
|
||||||
MemfsCaseInsensitive = 0x80000000,
|
MemfsCaseInsensitive = 0x80000000,
|
||||||
MemfsFlushAndPurgeOnCleanup = 0x40000000,
|
MemfsFlushAndPurgeOnCleanup = 0x40000000,
|
||||||
|
MemfsLegacyUnlinkRename = 0x20000000,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MemfsCreate(Flags, FileInfoTimeout, MaxFileNodes, MaxFileSize, VolumePrefix, RootSddl, PMemfs)\
|
#define MemfsCreate(Flags, FileInfoTimeout, MaxFileNodes, MaxFileSize, VolumePrefix, RootSddl, PMemfs)\
|
||||||
MemfsCreateFunnel(\
|
MemfsCreateFunnel(\
|
||||||
Flags,\
|
Flags,\
|
||||||
FileInfoTimeout,\
|
FileInfoTimeout,\
|
||||||
|
@ -43,7 +43,8 @@ void *memfs_start_ex(ULONG Flags, ULONG FileInfoTimeout)
|
|||||||
Result = MemfsCreateFunnel(
|
Result = MemfsCreateFunnel(
|
||||||
Flags |
|
Flags |
|
||||||
(OptCaseInsensitive ? MemfsCaseInsensitive : 0) |
|
(OptCaseInsensitive ? MemfsCaseInsensitive : 0) |
|
||||||
(OptFlushAndPurgeOnCleanup ? MemfsFlushAndPurgeOnCleanup : 0),
|
(OptFlushAndPurgeOnCleanup ? MemfsFlushAndPurgeOnCleanup : 0) |
|
||||||
|
(OptLegacyUnlinkRename ? MemfsLegacyUnlinkRename : 0),
|
||||||
FileInfoTimeout,
|
FileInfoTimeout,
|
||||||
1024,
|
1024,
|
||||||
1024 * 1024,
|
1024 * 1024,
|
||||||
|
@ -39,6 +39,7 @@ BOOLEAN OptCaseInsensitiveCmp = FALSE;
|
|||||||
BOOLEAN OptCaseInsensitive = FALSE;
|
BOOLEAN OptCaseInsensitive = FALSE;
|
||||||
BOOLEAN OptCaseRandomize = FALSE;
|
BOOLEAN OptCaseRandomize = FALSE;
|
||||||
BOOLEAN OptFlushAndPurgeOnCleanup = FALSE;
|
BOOLEAN OptFlushAndPurgeOnCleanup = FALSE;
|
||||||
|
BOOLEAN OptLegacyUnlinkRename = FALSE;
|
||||||
BOOLEAN OptNotify = FALSE;
|
BOOLEAN OptNotify = FALSE;
|
||||||
WCHAR OptOplock = 0;
|
WCHAR OptOplock = 0;
|
||||||
WCHAR OptMountPointBuf[MAX_PATH], *OptMountPoint;
|
WCHAR OptMountPointBuf[MAX_PATH], *OptMountPoint;
|
||||||
@ -296,6 +297,11 @@ int main(int argc, char *argv[])
|
|||||||
OptFlushAndPurgeOnCleanup = TRUE;
|
OptFlushAndPurgeOnCleanup = TRUE;
|
||||||
rmarg(argv, argc, argi);
|
rmarg(argv, argc, argi);
|
||||||
}
|
}
|
||||||
|
else if (0 == strcmp("--legacy-unlink-rename", a))
|
||||||
|
{
|
||||||
|
OptLegacyUnlinkRename = TRUE;
|
||||||
|
rmarg(argv, argc, argi);
|
||||||
|
}
|
||||||
else if (0 == strcmp("--notify", a))
|
else if (0 == strcmp("--notify", a))
|
||||||
{
|
{
|
||||||
OptNotify = TRUE;
|
OptNotify = TRUE;
|
||||||
|
@ -159,6 +159,7 @@ extern BOOLEAN OptCaseInsensitiveCmp;
|
|||||||
extern BOOLEAN OptCaseInsensitive;
|
extern BOOLEAN OptCaseInsensitive;
|
||||||
extern BOOLEAN OptCaseRandomize;
|
extern BOOLEAN OptCaseRandomize;
|
||||||
extern BOOLEAN OptFlushAndPurgeOnCleanup;
|
extern BOOLEAN OptFlushAndPurgeOnCleanup;
|
||||||
|
extern BOOLEAN OptLegacyUnlinkRename;
|
||||||
extern BOOLEAN OptNotify;
|
extern BOOLEAN OptNotify;
|
||||||
extern WCHAR OptOplock;
|
extern WCHAR OptOplock;
|
||||||
extern WCHAR OptMountPointBuf[], *OptMountPoint;
|
extern WCHAR OptMountPointBuf[], *OptMountPoint;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user