winfsp/inc/winfsp/winfsp.hpp
Colin Atkinson 791a2162a3 fix: Make FlushAndPurgeOnCleanup accessible in C++
Adds the appropriate setters and getters to the C++ API.
2019-02-22 11:14:48 -05:00

1321 lines
40 KiB
C++

/**
* @file winfsp/winfsp.hpp
* WinFsp C++ Layer.
*
* @copyright 2015-2018 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
*
* You can redistribute it and/or modify it under the terms of the GNU
* General Public License version 3 as published by the Free Software
* Foundation.
*
* Licensees holding a valid commercial license may use this software
* in accordance with the commercial license agreement provided in
* conjunction with the software. The terms and conditions of any such
* commercial license agreement shall govern, supersede, and render
* ineffective any application of the GPLv3 license to this software,
* notwithstanding of any reference thereto in the software or
* associated repository.
*/
#ifndef WINFSP_WINFSP_HPP_INCLUDED
#define WINFSP_WINFSP_HPP_INCLUDED
#ifndef __cplusplus
#error this header requires a C++ compiler
#endif
#include <winfsp/winfsp.h>
#define FSP_CPP_EXCEPTION_GUARD(...)\
try { __VA_ARGS__ } catch (...) { return self->ExceptionHandler(); }
#define FSP_CPP_EXCEPTION_GUARD_VOID(...)\
try { __VA_ARGS__ } catch (...) { self->ExceptionHandler(); return; }
namespace Fsp {
inline NTSTATUS Initialize()
{
static NTSTATUS LoadResult = FspLoad(0);
return LoadResult;
}
class FileSystemBase
{
public:
typedef FSP_FSCTL_VOLUME_INFO VolumeInfo;
typedef FSP_FSCTL_FILE_INFO FileInfo;
typedef FSP_FSCTL_OPEN_FILE_INFO OpenFileInfo;
typedef FSP_FSCTL_DIR_INFO DirInfo;
typedef FSP_FSCTL_STREAM_INFO StreamInfo;
enum CleanupFlags
{
CleanupDelete = FspCleanupDelete,
CleanupSetAllocationSize = FspCleanupSetAllocationSize,
CleanupSetArchiveBit = FspCleanupSetArchiveBit,
CleanupSetLastAccessTime = FspCleanupSetLastAccessTime,
CleanupSetLastWriteTime = FspCleanupSetLastWriteTime,
CleanupSetChangeTime = FspCleanupSetChangeTime,
};
public:
FileSystemBase()
{
}
virtual ~FileSystemBase()
{
}
/* operations */
virtual NTSTATUS ExceptionHandler()
{
return STATUS_UNEXPECTED_IO_ERROR;
}
virtual NTSTATUS Init(PVOID Host)
{
return STATUS_SUCCESS;
}
virtual NTSTATUS Mounted(PVOID Host)
{
return STATUS_SUCCESS;
}
virtual VOID Unmounted(PVOID Host)
{
}
virtual NTSTATUS GetVolumeInfo(
VolumeInfo *VolumeInfo)
{
return STATUS_INVALID_DEVICE_REQUEST;
}
virtual NTSTATUS SetVolumeLabel_(
PWSTR VolumeLabel,
VolumeInfo *VolumeInfo)
{
return STATUS_INVALID_DEVICE_REQUEST;
}
virtual NTSTATUS GetSecurityByName(
PWSTR FileName,
PUINT32 PFileAttributes/* or ReparsePointIndex */,
PSECURITY_DESCRIPTOR SecurityDescriptor,
SIZE_T *PSecurityDescriptorSize)
{
return STATUS_INVALID_DEVICE_REQUEST;
}
virtual NTSTATUS Create(
PWSTR FileName,
UINT32 CreateOptions,
UINT32 GrantedAccess,
UINT32 FileAttributes,
PSECURITY_DESCRIPTOR SecurityDescriptor,
UINT64 AllocationSize,
PVOID *PFileNode,
PVOID *PFileDesc,
OpenFileInfo *OpenFileInfo)
{
return STATUS_INVALID_DEVICE_REQUEST;
}
virtual NTSTATUS Open(
PWSTR FileName,
UINT32 CreateOptions,
UINT32 GrantedAccess,
PVOID *PFileNode,
PVOID *PFileDesc,
OpenFileInfo *OpenFileInfo)
{
return STATUS_INVALID_DEVICE_REQUEST;
}
virtual NTSTATUS Overwrite(
PVOID FileNode,
PVOID FileDesc,
UINT32 FileAttributes,
BOOLEAN ReplaceFileAttributes,
UINT64 AllocationSize,
FileInfo *FileInfo)
{
return STATUS_INVALID_DEVICE_REQUEST;
}
virtual VOID Cleanup(
PVOID FileNode,
PVOID FileDesc,
PWSTR FileName,
ULONG Flags)
{
}
virtual VOID Close(
PVOID FileNode,
PVOID FileDesc)
{
}
virtual NTSTATUS Read(
PVOID FileNode,
PVOID FileDesc,
PVOID Buffer,
UINT64 Offset,
ULONG Length,
PULONG PBytesTransferred)
{
return STATUS_INVALID_DEVICE_REQUEST;
}
virtual NTSTATUS Write(
PVOID FileNode,
PVOID FileDesc,
PVOID Buffer,
UINT64 Offset,
ULONG Length,
BOOLEAN WriteToEndOfFile,
BOOLEAN ConstrainedIo,
PULONG PBytesTransferred,
FileInfo *FileInfo)
{
return STATUS_INVALID_DEVICE_REQUEST;
}
virtual NTSTATUS Flush(
PVOID FileNode,
PVOID FileDesc,
FileInfo *FileInfo)
{
return STATUS_INVALID_DEVICE_REQUEST;
}
virtual NTSTATUS GetFileInfo(
PVOID FileNode,
PVOID FileDesc,
FileInfo *FileInfo)
{
return STATUS_INVALID_DEVICE_REQUEST;
}
virtual NTSTATUS SetBasicInfo(
PVOID FileNode,
PVOID FileDesc,
UINT32 FileAttributes,
UINT64 CreationTime,
UINT64 LastAccessTime,
UINT64 LastWriteTime,
UINT64 ChangeTime,
FileInfo *FileInfo)
{
return STATUS_INVALID_DEVICE_REQUEST;
}
virtual NTSTATUS SetFileSize(
PVOID FileNode,
PVOID FileDesc,
UINT64 NewSize,
BOOLEAN SetAllocationSize,
FileInfo *FileInfo)
{
return STATUS_INVALID_DEVICE_REQUEST;
}
virtual NTSTATUS CanDelete(
PVOID FileNode,
PVOID FileDesc,
PWSTR FileName)
{
return STATUS_INVALID_DEVICE_REQUEST;
}
virtual NTSTATUS Rename(
PVOID FileNode,
PVOID FileDesc,
PWSTR FileName,
PWSTR NewFileName,
BOOLEAN ReplaceIfExists)
{
return STATUS_INVALID_DEVICE_REQUEST;
}
virtual NTSTATUS GetSecurity(
PVOID FileNode,
PVOID FileDesc,
PSECURITY_DESCRIPTOR SecurityDescriptor,
SIZE_T *PSecurityDescriptorSize)
{
return STATUS_INVALID_DEVICE_REQUEST;
}
virtual NTSTATUS SetSecurity(
PVOID FileNode,
PVOID FileDesc,
SECURITY_INFORMATION SecurityInformation,
PSECURITY_DESCRIPTOR ModificationDescriptor)
{
return STATUS_INVALID_DEVICE_REQUEST;
}
virtual NTSTATUS ReadDirectory(
PVOID FileNode,
PVOID FileDesc,
PWSTR Pattern,
PWSTR Marker,
PVOID Buffer,
ULONG Length,
PULONG PBytesTransferred)
{
return SeekableReadDirectory(
FileNode,
FileDesc,
Pattern,
Marker,
Buffer,
Length,
PBytesTransferred);
}
virtual NTSTATUS ReadDirectoryEntry(
PVOID FileNode,
PVOID FileDesc,
PWSTR Pattern,
PWSTR Marker,
PVOID *PContext,
DirInfo *DirInfo)
{
return STATUS_INVALID_DEVICE_REQUEST;
}
virtual NTSTATUS ResolveReparsePoints(
PWSTR FileName,
UINT32 ReparsePointIndex,
BOOLEAN ResolveLastPathComponent,
PIO_STATUS_BLOCK PIoStatus,
PVOID Buffer,
PSIZE_T PSize)
{
return FspFileSystemResolveReparsePoints(
0,
GetReparsePointByName,
this,
FileName,
ReparsePointIndex,
ResolveLastPathComponent,
PIoStatus,
Buffer,
PSize);
}
virtual NTSTATUS GetReparsePointByName(
PWSTR FileName,
BOOLEAN IsDirectory,
PVOID Buffer,
PSIZE_T PSize)
{
return STATUS_INVALID_DEVICE_REQUEST;
}
virtual NTSTATUS GetReparsePoint(
PVOID FileNode,
PVOID FileDesc,
PWSTR FileName,
PVOID Buffer,
PSIZE_T PSize)
{
return STATUS_INVALID_DEVICE_REQUEST;
}
virtual NTSTATUS SetReparsePoint(
PVOID FileNode,
PVOID FileDesc,
PWSTR FileName,
PVOID Buffer,
SIZE_T Size)
{
return STATUS_INVALID_DEVICE_REQUEST;
}
virtual NTSTATUS DeleteReparsePoint(
PVOID FileNode,
PVOID FileDesc,
PWSTR FileName,
PVOID Buffer,
SIZE_T Size)
{
return STATUS_INVALID_DEVICE_REQUEST;
}
virtual NTSTATUS GetStreamInfo(
PVOID FileNode,
PVOID FileDesc,
PVOID Buffer,
ULONG Length,
PULONG PBytesTransferred)
{
return STATUS_INVALID_DEVICE_REQUEST;
}
/* helpers */
static NTSTATUS NtStatusFromWin32(DWORD Error)
{
return FspNtStatusFromWin32(Error);
}
static DWORD Win32FromNtStatus(NTSTATUS Status)
{
return FspWin32FromNtStatus(Status);
}
static VOID DeleteDirectoryBuffer(PVOID *PDirBuffer)
{
FspFileSystemDeleteDirectoryBuffer(PDirBuffer);
}
NTSTATUS SeekableReadDirectory(
PVOID FileNode,
PVOID FileDesc,
PWSTR Pattern,
PWSTR Marker,
PVOID Buffer,
ULONG Length,
PULONG PBytesTransferred)
{
PVOID Context = 0;
union
{
UINT8 B[FIELD_OFFSET(FileSystemBase::DirInfo, FileNameBuf) + MAX_PATH * sizeof(WCHAR)];
FileSystemBase::DirInfo D;
} DirInfoBuf;
FileSystemBase::DirInfo *DirInfo = &DirInfoBuf.D;
NTSTATUS Result = STATUS_SUCCESS;
*PBytesTransferred = 0;
for (;;)
{
Result = ReadDirectoryEntry(FileNode, FileDesc, Pattern, Marker, &Context, DirInfo);
if (STATUS_NO_MORE_FILES == Result)
{
Result = STATUS_SUCCESS;
break;
}
if (!NT_SUCCESS(Result))
break;
if (!FspFileSystemAddDirInfo(DirInfo, Buffer, Length, PBytesTransferred))
break;
}
if (!NT_SUCCESS(Result))
return Result;
return STATUS_SUCCESS;
}
NTSTATUS BufferedReadDirectory(
PVOID *PDirBuffer,
PVOID FileNode,
PVOID FileDesc,
PWSTR Pattern,
PWSTR Marker,
PVOID Buffer,
ULONG Length,
PULONG PBytesTransferred)
{
PVOID Context = 0;
union
{
UINT8 B[FIELD_OFFSET(FileSystemBase::DirInfo, FileNameBuf) + MAX_PATH * sizeof(WCHAR)];
FileSystemBase::DirInfo D;
} DirInfoBuf;
FileSystemBase::DirInfo *DirInfo = &DirInfoBuf.D;
NTSTATUS Result = STATUS_SUCCESS;
*PBytesTransferred = 0;
if (FspFileSystemAcquireDirectoryBuffer(PDirBuffer, 0 == Marker, &Result))
{
try
{
for (;;)
{
Result = ReadDirectoryEntry(FileNode, FileDesc, Pattern, Marker, &Context, DirInfo);
if (STATUS_NO_MORE_FILES == Result)
{
Result = STATUS_SUCCESS;
break;
}
if (!NT_SUCCESS(Result))
break;
if (!FspFileSystemFillDirectoryBuffer(PDirBuffer, DirInfo, &Result))
break;
}
}
catch (...)
{
FspFileSystemReleaseDirectoryBuffer(PDirBuffer);
throw;
}
FspFileSystemReleaseDirectoryBuffer(PDirBuffer);
}
if (!NT_SUCCESS(Result))
return Result;
FspFileSystemReadDirectoryBuffer(PDirBuffer, Marker, Buffer, Length, PBytesTransferred);
return STATUS_SUCCESS;
}
BOOLEAN FindReparsePoint(
PWSTR FileName, PUINT32 PReparsePointIndex)
{
return FspFileSystemFindReparsePoint(
0,
GetReparsePointByName,
this,
FileName,
PReparsePointIndex);
}
static NTSTATUS CanReplaceReparsePoint(
PVOID CurrentReparseData, SIZE_T CurrentReparseDataSize,
PVOID ReplaceReparseData, SIZE_T ReplaceReparseDataSize)
{
return FspFileSystemCanReplaceReparsePoint(
CurrentReparseData, CurrentReparseDataSize,
ReplaceReparseData, ReplaceReparseDataSize);
}
static BOOLEAN AddStreamInfo(StreamInfo *StreamInfo,
PVOID Buffer, ULONG Length, PULONG PBytesTransferred)
{
return FspFileSystemAddStreamInfo(StreamInfo, Buffer, Length, PBytesTransferred);
}
private:
static NTSTATUS GetReparsePointByName(FSP_FILE_SYSTEM *FileSystem,
PVOID Context,
PWSTR FileName,
BOOLEAN IsDirectory,
PVOID Buffer,
PSIZE_T PSize)
{
FileSystemBase *self = (FileSystemBase *)Context;
FSP_CPP_EXCEPTION_GUARD(
return self->GetReparsePointByName(
FileName,
IsDirectory,
Buffer,
PSize);
)
}
private:
/* disallow copy and assignment */
FileSystemBase(const FileSystemBase &);
FileSystemBase &operator=(const FileSystemBase &);
};
class FileSystemHost
{
public:
/* ctor/dtor */
FileSystemHost(FileSystemBase &FileSystem) :
_VolumeParams(), _FileSystemPtr(0), _FileSystem(&FileSystem)
{
Initialize();
_VolumeParams.UmFileContextIsFullContext = 1;
}
virtual ~FileSystemHost()
{
if (0 != _FileSystemPtr)
FspFileSystemDelete(_FileSystemPtr);
}
/* properties */
UINT16 SectorSize()
{
return _VolumeParams.SectorSize;
}
VOID SetSectorSize(UINT16 SectorSize)
{
_VolumeParams.SectorSize = SectorSize;
}
UINT16 SectorsPerAllocationUnit()
{
return _VolumeParams.SectorsPerAllocationUnit;
}
VOID SetSectorsPerAllocationUnit(UINT16 SectorsPerAllocationUnit)
{
_VolumeParams.SectorsPerAllocationUnit = SectorsPerAllocationUnit;
}
UINT16 MaxComponentLength()
{
return _VolumeParams.MaxComponentLength;
}
VOID SetMaxComponentLength(UINT16 MaxComponentLength)
{
_VolumeParams.MaxComponentLength = MaxComponentLength;
}
UINT64 VolumeCreationTime()
{
return _VolumeParams.VolumeCreationTime;
}
VOID SetVolumeCreationTime(UINT64 VolumeCreationTime)
{
_VolumeParams.VolumeCreationTime = VolumeCreationTime;
}
UINT32 VolumeSerialNumber()
{
return _VolumeParams.VolumeSerialNumber;
}
VOID SetVolumeSerialNumber(UINT32 VolumeSerialNumber)
{
_VolumeParams.VolumeSerialNumber = VolumeSerialNumber;
}
UINT32 FileInfoTimeout()
{
return _VolumeParams.FileInfoTimeout;
}
VOID SetFileInfoTimeout(UINT32 FileInfoTimeout)
{
_VolumeParams.FileInfoTimeout = FileInfoTimeout;
}
BOOLEAN CaseSensitiveSearch()
{
return _VolumeParams.CaseSensitiveSearch;
}
VOID SetCaseSensitiveSearch(BOOLEAN CaseSensitiveSearch)
{
_VolumeParams.CaseSensitiveSearch = !!CaseSensitiveSearch;
}
BOOLEAN CasePreservedNames()
{
return _VolumeParams.CasePreservedNames;
}
VOID SetCasePreservedNames(BOOLEAN CasePreservedNames)
{
_VolumeParams.CasePreservedNames = !!CasePreservedNames;
}
BOOLEAN UnicodeOnDisk()
{
return _VolumeParams.UnicodeOnDisk;
}
VOID SetUnicodeOnDisk(BOOLEAN UnicodeOnDisk)
{
_VolumeParams.UnicodeOnDisk = !!UnicodeOnDisk;
}
BOOLEAN PersistentAcls()
{
return _VolumeParams.PersistentAcls;
}
VOID SetPersistentAcls(BOOLEAN PersistentAcls)
{
_VolumeParams.PersistentAcls = !!PersistentAcls;
}
BOOLEAN ReparsePoints()
{
return _VolumeParams.ReparsePoints;
}
VOID SetReparsePoints(BOOLEAN ReparsePoints)
{
_VolumeParams.ReparsePoints = !!ReparsePoints;
}
BOOLEAN ReparsePointsAccessCheck()
{
return _VolumeParams.ReparsePointsAccessCheck;
}
VOID SetReparsePointsAccessCheck(BOOLEAN ReparsePointsAccessCheck)
{
_VolumeParams.ReparsePointsAccessCheck = !!ReparsePointsAccessCheck;
}
BOOLEAN NamedStreams()
{
return _VolumeParams.NamedStreams;
}
VOID SetNamedStreams(BOOLEAN NamedStreams)
{
_VolumeParams.NamedStreams = !!NamedStreams;
}
BOOLEAN PostCleanupWhenModifiedOnly()
{
return _VolumeParams.PostCleanupWhenModifiedOnly;
}
VOID SetPostCleanupWhenModifiedOnly(BOOLEAN PostCleanupWhenModifiedOnly)
{
_VolumeParams.PostCleanupWhenModifiedOnly = !!PostCleanupWhenModifiedOnly;
}
BOOLEAN PassQueryDirectoryPattern()
{
return _VolumeParams.PassQueryDirectoryPattern;
}
VOID SetPassQueryDirectoryPattern(BOOLEAN PassQueryDirectoryPattern)
{
_VolumeParams.PassQueryDirectoryPattern = !!PassQueryDirectoryPattern;
}
BOOLEAN FlushAndPurgeOnCleanup()
{
return _VolumeParams.FlushAndPurgeOnCleanup;
}
VOID SetFlushAndPurgeOnCleanup(BOOLEAN FlushAndPurgeOnCleanup)
{
_VolumeParams.FlushAndPurgeOnCleanup = !!FlushAndPurgeOnCleanup;
}
PWSTR Prefix()
{
return _VolumeParams.Prefix;
}
VOID SetPrefix(PWSTR Prefix)
{
int Size = lstrlenW(Prefix) * sizeof(WCHAR);
if (Size > sizeof _VolumeParams.Prefix - sizeof(WCHAR))
Size = sizeof _VolumeParams.Prefix - sizeof(WCHAR);
RtlCopyMemory(_VolumeParams.Prefix, Prefix, Size);
_VolumeParams.Prefix[Size / sizeof(WCHAR)] = L'\0';
}
PWSTR FileSystemName()
{
return _VolumeParams.FileSystemName;
}
VOID SetFileSystemName(PWSTR FileSystemName)
{
int Size = lstrlenW(FileSystemName) * sizeof(WCHAR);
if (Size > sizeof _VolumeParams.FileSystemName - sizeof(WCHAR))
Size = sizeof _VolumeParams.FileSystemName - sizeof(WCHAR);
RtlCopyMemory(_VolumeParams.FileSystemName, FileSystemName, Size);
_VolumeParams.FileSystemName[Size / sizeof(WCHAR)] = L'\0';
}
/* control */
NTSTATUS Preflight(PWSTR MountPoint)
{
return FspFileSystemPreflight(
_VolumeParams.Prefix[0] ? L"WinFsp.Net" : L"WinFsp.Disk",
MountPoint);
}
NTSTATUS Mount(PWSTR MountPoint,
PSECURITY_DESCRIPTOR SecurityDescriptor = 0,
BOOLEAN Synchronized = FALSE,
UINT32 DebugLog = 0)
{
NTSTATUS Result;
try
{
Result = _FileSystem->Init(this);
}
catch (...)
{
Result = _FileSystem->ExceptionHandler();
}
if (!NT_SUCCESS(Result))
return Result;
Result = FspFileSystemCreate(
_VolumeParams.Prefix[0] ? L"WinFsp.Net" : L"WinFsp.Disk",
&_VolumeParams, Interface(), &_FileSystemPtr);
if (!NT_SUCCESS(Result))
return Result;
_FileSystemPtr->UserContext = _FileSystem;
FspFileSystemSetOperationGuardStrategy(_FileSystemPtr, Synchronized ?
FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_COARSE :
FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_FINE);
FspFileSystemSetDebugLog(_FileSystemPtr, DebugLog);
Result = FspFileSystemSetMountPointEx(_FileSystemPtr, MountPoint, SecurityDescriptor);
if (NT_SUCCESS(Result))
{
try
{
Result = _FileSystem->Mounted(this);
}
catch (...)
{
Result = _FileSystem->ExceptionHandler();
}
if (NT_SUCCESS(Result))
{
Result = FspFileSystemStartDispatcher(_FileSystemPtr, 0);
if (!NT_SUCCESS(Result))
try
{
_FileSystem->Unmounted(this);
}
catch (...)
{
_FileSystem->ExceptionHandler();
}
}
}
if (!NT_SUCCESS(Result))
{
FspFileSystemDelete(_FileSystemPtr);
_FileSystemPtr = 0;
}
return Result;
}
VOID Unmount()
{
FspFileSystemStopDispatcher(_FileSystemPtr);
try
{
_FileSystem->Unmounted(this);
}
catch (...)
{
_FileSystem->ExceptionHandler();
}
_FileSystemPtr->UserContext = 0;
FspFileSystemDelete(_FileSystemPtr);
_FileSystemPtr = 0;
}
PWSTR MountPoint()
{
return 0 != _FileSystemPtr ? FspFileSystemMountPoint(_FileSystemPtr) : 0;
}
FSP_FILE_SYSTEM *FileSystemHandle()
{
return _FileSystemPtr;
}
FileSystemBase &FileSystem()
{
return *_FileSystem;
}
static NTSTATUS SetDebugLogFile(PWSTR FileName)
{
HANDLE Handle;
if ('-' == FileName[0] && '\0' == FileName[1])
Handle = GetStdHandle(STD_ERROR_HANDLE);
else
Handle = CreateFileW(
FileName,
FILE_APPEND_DATA,
FILE_SHARE_READ | FILE_SHARE_WRITE,
0,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
0);
if (INVALID_HANDLE_VALUE == Handle)
return FspNtStatusFromWin32(GetLastError());
FspDebugLogSetHandle(Handle);
return STATUS_SUCCESS;
}
private:
/* FSP_FILE_SYSTEM_INTERFACE */
static NTSTATUS GetVolumeInfo(FSP_FILE_SYSTEM *FileSystem0,
FSP_FSCTL_VOLUME_INFO *VolumeInfo)
{
FileSystemBase *self = (FileSystemBase *)FileSystem0->UserContext;
FSP_CPP_EXCEPTION_GUARD(
return self->GetVolumeInfo(
VolumeInfo);
)
}
static NTSTATUS SetVolumeLabel_(FSP_FILE_SYSTEM *FileSystem0,
PWSTR VolumeLabel,
FSP_FSCTL_VOLUME_INFO *VolumeInfo)
{
FileSystemBase *self = (FileSystemBase *)FileSystem0->UserContext;
FSP_CPP_EXCEPTION_GUARD(
return self->SetVolumeLabel_(
VolumeLabel,
VolumeInfo);
)
}
static NTSTATUS GetSecurityByName(FSP_FILE_SYSTEM *FileSystem0,
PWSTR FileName,
PUINT32 PFileAttributes/* or ReparsePointIndex */,
PSECURITY_DESCRIPTOR SecurityDescriptor,
SIZE_T *PSecurityDescriptorSize)
{
FileSystemBase *self = (FileSystemBase *)FileSystem0->UserContext;
FSP_CPP_EXCEPTION_GUARD(
return self->GetSecurityByName(
FileName,
PFileAttributes,
SecurityDescriptor,
PSecurityDescriptorSize);
)
}
static NTSTATUS Create(FSP_FILE_SYSTEM *FileSystem0,
PWSTR FileName,
UINT32 CreateOptions,
UINT32 GrantedAccess,
UINT32 FileAttributes,
PSECURITY_DESCRIPTOR SecurityDescriptor,
UINT64 AllocationSize,
PVOID *FullContext,
FSP_FSCTL_FILE_INFO *FileInfo)
{
FileSystemBase *self = (FileSystemBase *)FileSystem0->UserContext;
PVOID FileNode, FileDesc;
NTSTATUS Result;
FSP_CPP_EXCEPTION_GUARD(
Result = self->Create(
FileName,
CreateOptions,
GrantedAccess,
FileAttributes,
SecurityDescriptor,
AllocationSize,
&FileNode,
&FileDesc,
FspFileSystemGetOpenFileInfo(FileInfo));
)
((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext = (UINT64)(UINT_PTR)FileNode;
((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext2 = (UINT64)(UINT_PTR)FileDesc;
return Result;
}
static NTSTATUS Open(FSP_FILE_SYSTEM *FileSystem0,
PWSTR FileName,
UINT32 CreateOptions,
UINT32 GrantedAccess,
PVOID *FullContext,
FSP_FSCTL_FILE_INFO *FileInfo)
{
FileSystemBase *self = (FileSystemBase *)FileSystem0->UserContext;
PVOID FileNode, FileDesc;
NTSTATUS Result;
FSP_CPP_EXCEPTION_GUARD(
Result = self->Open(
FileName,
CreateOptions,
GrantedAccess,
&FileNode,
&FileDesc,
FspFileSystemGetOpenFileInfo(FileInfo));
)
((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext = (UINT64)(UINT_PTR)FileNode;
((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext2 = (UINT64)(UINT_PTR)FileDesc;
return Result;
}
static NTSTATUS Overwrite(FSP_FILE_SYSTEM *FileSystem0,
PVOID FullContext,
UINT32 FileAttributes,
BOOLEAN ReplaceFileAttributes,
UINT64 AllocationSize,
FSP_FSCTL_FILE_INFO *FileInfo)
{
FileSystemBase *self = (FileSystemBase *)FileSystem0->UserContext;
FSP_CPP_EXCEPTION_GUARD(
return self->Overwrite(
(PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext,
(PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext2,
FileAttributes,
ReplaceFileAttributes,
AllocationSize,
FileInfo);
)
}
static VOID Cleanup(FSP_FILE_SYSTEM *FileSystem0,
PVOID FullContext,
PWSTR FileName,
ULONG Flags)
{
FileSystemBase *self = (FileSystemBase *)FileSystem0->UserContext;
FSP_CPP_EXCEPTION_GUARD_VOID(
return self->Cleanup(
(PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext,
(PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext2,
FileName,
Flags);
)
}
static VOID Close(FSP_FILE_SYSTEM *FileSystem0,
PVOID FullContext)
{
FileSystemBase *self = (FileSystemBase *)FileSystem0->UserContext;
FSP_CPP_EXCEPTION_GUARD_VOID(
return self->Close(
(PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext,
(PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext2);
)
}
static NTSTATUS Read(FSP_FILE_SYSTEM *FileSystem0,
PVOID FullContext,
PVOID Buffer,
UINT64 Offset,
ULONG Length,
PULONG PBytesTransferred)
{
FileSystemBase *self = (FileSystemBase *)FileSystem0->UserContext;
FSP_CPP_EXCEPTION_GUARD(
return self->Read(
(PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext,
(PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext2,
Buffer,
Offset,
Length,
PBytesTransferred);
)
}
static NTSTATUS Write(FSP_FILE_SYSTEM *FileSystem0,
PVOID FullContext,
PVOID Buffer,
UINT64 Offset,
ULONG Length,
BOOLEAN WriteToEndOfFile,
BOOLEAN ConstrainedIo,
PULONG PBytesTransferred,
FSP_FSCTL_FILE_INFO *FileInfo)
{
FileSystemBase *self = (FileSystemBase *)FileSystem0->UserContext;
FSP_CPP_EXCEPTION_GUARD(
return self->Write(
(PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext,
(PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext2,
Buffer,
Offset,
Length,
WriteToEndOfFile,
ConstrainedIo,
PBytesTransferred,
FileInfo);
)
}
static NTSTATUS Flush(FSP_FILE_SYSTEM *FileSystem0,
PVOID FullContext,
FSP_FSCTL_FILE_INFO *FileInfo)
{
FileSystemBase *self = (FileSystemBase *)FileSystem0->UserContext;
FSP_CPP_EXCEPTION_GUARD(
return self->Flush(
(PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext,
(PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext2,
FileInfo);
)
}
static NTSTATUS GetFileInfo(FSP_FILE_SYSTEM *FileSystem0,
PVOID FullContext,
FSP_FSCTL_FILE_INFO *FileInfo)
{
FileSystemBase *self = (FileSystemBase *)FileSystem0->UserContext;
FSP_CPP_EXCEPTION_GUARD(
return self->GetFileInfo(
(PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext,
(PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext2,
FileInfo);
)
}
static NTSTATUS SetBasicInfo(FSP_FILE_SYSTEM *FileSystem0,
PVOID FullContext,
UINT32 FileAttributes,
UINT64 CreationTime,
UINT64 LastAccessTime,
UINT64 LastWriteTime,
UINT64 ChangeTime,
FSP_FSCTL_FILE_INFO *FileInfo)
{
FileSystemBase *self = (FileSystemBase *)FileSystem0->UserContext;
FSP_CPP_EXCEPTION_GUARD(
return self->SetBasicInfo(
(PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext,
(PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext2,
FileAttributes,
CreationTime,
LastAccessTime,
LastWriteTime,
ChangeTime,
FileInfo);
)
}
static NTSTATUS SetFileSize(FSP_FILE_SYSTEM *FileSystem0,
PVOID FullContext,
UINT64 NewSize,
BOOLEAN SetAllocationSize,
FSP_FSCTL_FILE_INFO *FileInfo)
{
FileSystemBase *self = (FileSystemBase *)FileSystem0->UserContext;
FSP_CPP_EXCEPTION_GUARD(
return self->SetFileSize(
(PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext,
(PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext2,
NewSize,
SetAllocationSize,
FileInfo);
)
}
static NTSTATUS CanDelete(FSP_FILE_SYSTEM *FileSystem0,
PVOID FullContext,
PWSTR FileName)
{
FileSystemBase *self = (FileSystemBase *)FileSystem0->UserContext;
FSP_CPP_EXCEPTION_GUARD(
return self->CanDelete(
(PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext,
(PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext2,
FileName);
)
}
static NTSTATUS Rename(FSP_FILE_SYSTEM *FileSystem0,
PVOID FullContext,
PWSTR FileName,
PWSTR NewFileName,
BOOLEAN ReplaceIfExists)
{
FileSystemBase *self = (FileSystemBase *)FileSystem0->UserContext;
FSP_CPP_EXCEPTION_GUARD(
return self->Rename(
(PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext,
(PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext2,
FileName,
NewFileName,
ReplaceIfExists);
)
}
static NTSTATUS GetSecurity(FSP_FILE_SYSTEM *FileSystem0,
PVOID FullContext,
PSECURITY_DESCRIPTOR SecurityDescriptor,
SIZE_T *PSecurityDescriptorSize)
{
FileSystemBase *self = (FileSystemBase *)FileSystem0->UserContext;
FSP_CPP_EXCEPTION_GUARD(
return self->GetSecurity(
(PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext,
(PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext2,
SecurityDescriptor,
PSecurityDescriptorSize);
)
}
static NTSTATUS SetSecurity(FSP_FILE_SYSTEM *FileSystem0,
PVOID FullContext,
SECURITY_INFORMATION SecurityInformation,
PSECURITY_DESCRIPTOR ModificationDescriptor)
{
FileSystemBase *self = (FileSystemBase *)FileSystem0->UserContext;
FSP_CPP_EXCEPTION_GUARD(
return self->SetSecurity(
(PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext,
(PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext2,
SecurityInformation,
ModificationDescriptor);
)
}
static NTSTATUS ReadDirectory(FSP_FILE_SYSTEM *FileSystem0,
PVOID FullContext,
PWSTR Pattern,
PWSTR Marker,
PVOID Buffer,
ULONG Length,
PULONG PBytesTransferred)
{
FileSystemBase *self = (FileSystemBase *)FileSystem0->UserContext;
FSP_CPP_EXCEPTION_GUARD(
return self->ReadDirectory(
(PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext,
(PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext2,
Pattern,
Marker,
Buffer,
Length,
PBytesTransferred);
)
}
static NTSTATUS ResolveReparsePoints(FSP_FILE_SYSTEM *FileSystem0,
PWSTR FileName,
UINT32 ReparsePointIndex,
BOOLEAN ResolveLastPathComponent,
PIO_STATUS_BLOCK PIoStatus,
PVOID Buffer,
PSIZE_T PSize)
{
FileSystemBase *self = (FileSystemBase *)FileSystem0->UserContext;
FSP_CPP_EXCEPTION_GUARD(
return self->ResolveReparsePoints(
FileName,
ReparsePointIndex,
ResolveLastPathComponent,
PIoStatus,
Buffer,
PSize);
)
}
static NTSTATUS GetReparsePoint(FSP_FILE_SYSTEM *FileSystem0,
PVOID FullContext,
PWSTR FileName,
PVOID Buffer,
PSIZE_T PSize)
{
FileSystemBase *self = (FileSystemBase *)FileSystem0->UserContext;
FSP_CPP_EXCEPTION_GUARD(
return self->GetReparsePoint(
(PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext,
(PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext2,
FileName,
Buffer,
PSize);
)
}
static NTSTATUS SetReparsePoint(FSP_FILE_SYSTEM *FileSystem0,
PVOID FullContext,
PWSTR FileName,
PVOID Buffer,
SIZE_T Size)
{
FileSystemBase *self = (FileSystemBase *)FileSystem0->UserContext;
FSP_CPP_EXCEPTION_GUARD(
return self->SetReparsePoint(
(PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext,
(PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext2,
FileName,
Buffer,
Size);
)
}
static NTSTATUS DeleteReparsePoint(FSP_FILE_SYSTEM *FileSystem0,
PVOID FullContext,
PWSTR FileName,
PVOID Buffer,
SIZE_T Size)
{
FileSystemBase *self = (FileSystemBase *)FileSystem0->UserContext;
FSP_CPP_EXCEPTION_GUARD(
return self->DeleteReparsePoint(
(PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext,
(PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext2,
FileName,
Buffer,
Size);
)
}
static NTSTATUS GetStreamInfo(FSP_FILE_SYSTEM *FileSystem0,
PVOID FullContext,
PVOID Buffer,
ULONG Length,
PULONG PBytesTransferred)
{
FileSystemBase *self = (FileSystemBase *)FileSystem0->UserContext;
FSP_CPP_EXCEPTION_GUARD(
return self->GetStreamInfo(
(PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext,
(PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext2,
Buffer,
Length,
PBytesTransferred);
)
}
static FSP_FILE_SYSTEM_INTERFACE *Interface()
{
static FSP_FILE_SYSTEM_INTERFACE _Interface =
{
GetVolumeInfo,
SetVolumeLabel_,
GetSecurityByName,
Create,
Open,
Overwrite,
Cleanup,
Close,
Read,
Write,
Flush,
GetFileInfo,
SetBasicInfo,
SetFileSize,
CanDelete,
Rename,
GetSecurity,
SetSecurity,
ReadDirectory,
ResolveReparsePoints,
GetReparsePoint,
SetReparsePoint,
DeleteReparsePoint,
GetStreamInfo,
};
return &_Interface;
}
private:
/* disallow copy and assignment */
FileSystemHost(const FileSystemHost &);
FileSystemHost &operator=(const FileSystemHost &);
private:
FSP_FSCTL_VOLUME_PARAMS _VolumeParams;
FSP_FILE_SYSTEM *_FileSystemPtr;
FileSystemBase *_FileSystem;
};
class Service
{
public:
/* ctor/dtor */
Service(PWSTR ServiceName) : _Service(0)
{
Initialize();
FspServiceCreate(ServiceName, OnStart, OnStop, 0, &_Service);
if (0 != _Service)
_Service->UserContext = this;
}
virtual ~Service()
{
if (0 != _Service)
FspServiceDelete(_Service);
}
/* control */
ULONG Run()
{
if (0 == _Service)
{
FspServiceLog(EVENTLOG_ERROR_TYPE,
L"The service cannot be created (Status=%lx).",
STATUS_INSUFFICIENT_RESOURCES);
return FspWin32FromNtStatus(STATUS_INSUFFICIENT_RESOURCES);
}
FspServiceAllowConsoleMode(_Service);
NTSTATUS Result = FspServiceLoop(_Service);
ULONG ExitCode = FspServiceGetExitCode(_Service);
if (!NT_SUCCESS(Result))
{
FspServiceLog(EVENTLOG_ERROR_TYPE,
L"The service has failed to run (Status=%lx).",
Result);
return FspWin32FromNtStatus(Result);
}
return ExitCode;
}
VOID Stop()
{
if (0 == _Service)
return;
FspServiceStop(_Service);
}
VOID RequestTime(ULONG Time)
{
if (0 == _Service)
return;
FspServiceRequestTime(_Service, Time);
}
ULONG GetExitCode()
{
return 0 != _Service ? FspServiceGetExitCode(_Service) : ERROR_NO_SYSTEM_RESOURCES;
}
VOID SetExitCode(ULONG ExitCode)
{
if (0 == _Service)
return;
FspServiceSetExitCode(_Service, ExitCode);
}
FSP_SERVICE *ServiceHandle()
{
return _Service;
}
static VOID Log(ULONG Type, PWSTR Format, ...)
{
va_list ap;
va_start(ap, Format);
FspServiceLogV(Type, Format, ap);
va_end(ap);
}
static VOID LogV(ULONG Type, PWSTR Format, va_list ap)
{
FspServiceLogV(Type, Format, ap);
}
protected:
/* start/stop */
virtual NTSTATUS ExceptionHandler()
{
return 0xE06D7363/*STATUS_CPP_EH_EXCEPTION*/;
}
virtual NTSTATUS OnStart(ULONG Argc, PWSTR *Argv)
{
return STATUS_SUCCESS;
}
virtual NTSTATUS OnStop()
{
return STATUS_SUCCESS;
}
private:
/* callbacks */
static NTSTATUS OnStart(FSP_SERVICE *Service0, ULONG Argc, PWSTR *Argv)
{
Service *self = (Service *)Service0->UserContext;
FSP_CPP_EXCEPTION_GUARD(
return self->OnStart(Argc, Argv);
)
}
static NTSTATUS OnStop(FSP_SERVICE *Service0)
{
Service *self = (Service *)Service0->UserContext;
FSP_CPP_EXCEPTION_GUARD(
return self->OnStop();
)
}
private:
/* disallow copy and assignment */
Service(const Service &);
Service &operator=(const Service &);
private:
FSP_SERVICE *_Service;
};
}
#undef FSP_CPP_EXCEPTION_GUARD
#undef FSP_CPP_EXCEPTION_GUARD_VOID
#endif