diff --git a/build/VStudio/winfsp_dll.vcxproj b/build/VStudio/winfsp_dll.vcxproj index aa5087cb..7bee8cb9 100644 --- a/build/VStudio/winfsp_dll.vcxproj +++ b/build/VStudio/winfsp_dll.vcxproj @@ -26,6 +26,7 @@ + diff --git a/build/VStudio/winfsp_dll.vcxproj.filters b/build/VStudio/winfsp_dll.vcxproj.filters index ad42357b..4b1f7e2b 100644 --- a/build/VStudio/winfsp_dll.vcxproj.filters +++ b/build/VStudio/winfsp_dll.vcxproj.filters @@ -50,6 +50,9 @@ Source\fuse + + Include\winfsp + diff --git a/inc/winfsp/winfsp.hpp b/inc/winfsp/winfsp.hpp new file mode 100644 index 00000000..982c9a4a --- /dev/null +++ b/inc/winfsp/winfsp.hpp @@ -0,0 +1,701 @@ +/** + * @file winfsp/winfsp.hpp + * WinFsp C++ Layer. + * + * @copyright 2015-2017 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 file in + * accordance with the commercial license agreement provided with the + * software. + */ + +#ifndef WINFSP_WINFSP_HPP_INCLUDED +#define WINFSP_WINFSP_HPP_INCLUDED + +#ifndef __cplusplus +#error this header requires a C++ compiler +#endif + +#include + +namespace Fsp +{ + +class FileSystem +{ +public: + typedef FSP_FSCTL_VOLUME_PARAMS VOLUME_PARAMS; + typedef FSP_FSCTL_VOLUME_INFO VOLUME_INFO; + typedef FSP_FSCTL_FILE_INFO FILE_INFO; + typedef FSP_FSCTL_OPEN_FILE_INFO OPEN_FILE_INFO; + typedef FSP_FSCTL_DIR_INFO DIR_INFO; + typedef FSP_FSCTL_STREAM_INFO STREAM_INFO; + struct FILE_CONTEXT + { + PVOID FileNode; + PVOID FileDesc; + }; + enum CLEANUP_FLAGS + { + Delete = FspCleanupDelete, + SetAllocationSize = FspCleanupSetAllocationSize, + SetArchiveBit = FspCleanupSetArchiveBit, + SetLastAccessTime = FspCleanupSetLastAccessTime, + SetLastWriteTime = FspCleanupSetLastWriteTime, + SetChangeTime = FspCleanupSetChangeTime, + }; + +public: + /* ctor/dtor */ + FileSystem() : _VolumeParams(), _FileSystem(0) + { + static NTSTATUS LoadResult = FspLoad(0); + _VolumeParams.SectorSize = 4096; + _VolumeParams.SectorsPerAllocationUnit = 1; + _VolumeParams.MaxComponentLength = 255; + GetSystemTimeAsFileTime((PFILETIME)&_VolumeParams.VolumeCreationTime); + _VolumeParams.VolumeSerialNumber = (UINT32)(_VolumeParams.VolumeCreationTime / (10000 * 1000)); + _VolumeParams.UmFileContextIsUserContext2 = 1; + } + virtual ~FileSystem() + { + if (0 != _FileSystem) + FspFileSystemDelete(_FileSystem); + } + + /* properties */ + const VOLUME_PARAMS *VolumeParams() + { + return &_VolumeParams; + } + VOID SetSectorSize(UINT16 SectorSize) + { + _VolumeParams.SectorSize = SectorSize; + } + VOID SetSectorsPerAllocationUnit(UINT16 SectorsPerAllocationUnit) + { + _VolumeParams.SectorsPerAllocationUnit = SectorsPerAllocationUnit; + } + VOID SetMaxComponentLength(UINT16 MaxComponentLength) + { + _VolumeParams.MaxComponentLength = MaxComponentLength; + } + VOID SetVolumeCreationTime(UINT64 VolumeCreationTime) + { + _VolumeParams.VolumeCreationTime = VolumeCreationTime; + } + VOID SetVolumeSerialNumber(UINT32 VolumeSerialNumber) + { + _VolumeParams.VolumeSerialNumber = VolumeSerialNumber; + } + VOID SetFileInfoTimeout(UINT32 FileInfoTimeout) + { + _VolumeParams.FileInfoTimeout = FileInfoTimeout; + } + VOID SetCaseSensitiveSearch(BOOLEAN CaseSensitiveSearch) + { + _VolumeParams.CaseSensitiveSearch = !!CaseSensitiveSearch; + } + VOID SetCasePreservedNames(BOOLEAN CasePreservedNames) + { + _VolumeParams.CasePreservedNames = !!CasePreservedNames; + } + VOID SetUnicodeOnDisk(BOOLEAN UnicodeOnDisk) + { + _VolumeParams.UnicodeOnDisk = !!UnicodeOnDisk; + } + VOID SetPersistentAcls(BOOLEAN PersistentAcls) + { + _VolumeParams.PersistentAcls = !!PersistentAcls; + } + VOID SetReparsePoints(BOOLEAN ReparsePoints) + { + _VolumeParams.ReparsePoints = !!ReparsePoints; + } + VOID SetReparsePointsAccessCheck(BOOLEAN ReparsePointsAccessCheck) + { + _VolumeParams.ReparsePointsAccessCheck = !!ReparsePointsAccessCheck; + } + VOID SetNamedStreams(BOOLEAN NamedStreams) + { + _VolumeParams.NamedStreams = !!NamedStreams; + } + VOID SetPostCleanupWhenModifiedOnly(BOOLEAN PostCleanupWhenModifiedOnly) + { + _VolumeParams.PostCleanupWhenModifiedOnly = !!PostCleanupWhenModifiedOnly; + } + VOID SetPassQueryDirectoryPattern(BOOLEAN PassQueryDirectoryPattern) + { + _VolumeParams.PassQueryDirectoryPattern = !!PassQueryDirectoryPattern; + } + 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'; + } + 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, + BOOLEAN Synchronized = FALSE, + UINT32 DebugLog = 0) + { + NTSTATUS Result; + Result = FspFileSystemCreate( + _VolumeParams.Prefix[0] ? L"WinFsp.Net" : L"WinFsp.Disk", + &_VolumeParams, Interface(), &_FileSystem); + if (NT_SUCCESS(Result)) + { + Result = FspFileSystemSetMountPoint(_FileSystem, MountPoint); + if (NT_SUCCESS(Result)) + Result = FspFileSystemStartDispatcher(_FileSystem, 0); + } + if (NT_SUCCESS(Result)) + { + _FileSystem->UserContext = this; + FspFileSystemSetOperationGuardStrategy(_FileSystem, Synchronized ? + FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_COARSE : + FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_FINE); + FspFileSystemSetDebugLog(_FileSystem, DebugLog); + } + else if (0 != _FileSystem) + { + FspFileSystemDelete(_FileSystem); + _FileSystem = 0; + } + return Result; + } + VOID Unmount() + { + FspFileSystemStopDispatcher(_FileSystem); + FspFileSystemDelete(_FileSystem); + _FileSystem = 0; + } + PWSTR MountPoint() + { + return 0 != _FileSystem ? FspFileSystemMountPoint(_FileSystem) : 0; + } + FSP_FILE_SYSTEM *FileSystemHandle() + { + return _FileSystem; + } + + /* helpers: directories/streams */ + static BOOLEAN AcquireDirectoryBuffer(PVOID *PDirBuffer, + BOOLEAN Reset, PNTSTATUS PResult) + { + return FspFileSystemAcquireDirectoryBuffer(PDirBuffer, Reset, PResult); + } + static BOOLEAN FillDirectoryBuffer(PVOID *PDirBuffer, + DIR_INFO *DirInfo, PNTSTATUS PResult) + { + return FspFileSystemFillDirectoryBuffer(PDirBuffer, DirInfo, PResult); + } + static VOID ReleaseDirectoryBuffer(PVOID *PDirBuffer) + { + FspFileSystemReleaseDirectoryBuffer(PDirBuffer); + } + static VOID ReadDirectoryBuffer(PVOID *PDirBuffer, + PWSTR Marker, + PVOID Buffer, ULONG Length, PULONG PBytesTransferred) + { + FspFileSystemReadDirectoryBuffer(PDirBuffer, + Marker, Buffer, Length, PBytesTransferred); + } + static VOID DeleteDirectoryBuffer(PVOID *PDirBuffer) + { + FspFileSystemDeleteDirectoryBuffer(PDirBuffer); + } + static BOOLEAN AddDirInfo(DIR_INFO *DirInfo, + PVOID Buffer, ULONG Length, PULONG PBytesTransferred) + { + return FspFileSystemAddDirInfo(DirInfo, Buffer, Length, PBytesTransferred); + } + static BOOLEAN AddStreamInfo(STREAM_INFO *StreamInfo, + PVOID Buffer, ULONG Length, PULONG PBytesTransferred) + { + return FspFileSystemAddStreamInfo(StreamInfo, Buffer, Length, PBytesTransferred); + } + + /* helpers: reparse points */ + BOOLEAN FindReparsePoint( + PWSTR FileName, PUINT32 PReparsePointIndex) + { + return FspFileSystemFindReparsePoint(_FileSystem, GetReparsePointByName, 0, + FileName, PReparsePointIndex); + } + static NTSTATUS CanReplaceReparsePoint( + PVOID CurrentReparseData, SIZE_T CurrentReparseDataSize, + PVOID ReplaceReparseData, SIZE_T ReplaceReparseDataSize) + { + return FspFileSystemCanReplaceReparsePoint( + CurrentReparseData, CurrentReparseDataSize, + ReplaceReparseData, ReplaceReparseDataSize); + } + + /* operations */ + virtual NTSTATUS GetVolumeInfo( + VOLUME_INFO *VolumeInfo) + { + return STATUS_INVALID_DEVICE_REQUEST; + } + virtual NTSTATUS SetVolumeLabel_( + PWSTR VolumeLabel, + VOLUME_INFO *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, + FILE_CONTEXT *FileContext, OPEN_FILE_INFO *OpenFileInfo) + { + return STATUS_INVALID_DEVICE_REQUEST; + } + virtual NTSTATUS Open( + PWSTR FileName, UINT32 CreateOptions, UINT32 GrantedAccess, + FILE_CONTEXT *FileContext, OPEN_FILE_INFO *OpenFileInfo) + { + return STATUS_INVALID_DEVICE_REQUEST; + } + virtual NTSTATUS Overwrite( + const FILE_CONTEXT *FileContext, UINT32 FileAttributes, BOOLEAN ReplaceFileAttributes, UINT64 AllocationSize, + FILE_INFO *FileInfo) + { + return STATUS_INVALID_DEVICE_REQUEST; + } + virtual VOID Cleanup( + const FILE_CONTEXT *FileContext, PWSTR FileName, ULONG Flags) + { + } + virtual VOID Close( + const FILE_CONTEXT *FileContext) + { + } + virtual NTSTATUS Read( + const FILE_CONTEXT *FileContext, PVOID Buffer, UINT64 Offset, ULONG Length, + PULONG PBytesTransferred) + { + return STATUS_INVALID_DEVICE_REQUEST; + } + virtual NTSTATUS Write( + const FILE_CONTEXT *FileContext, PVOID Buffer, UINT64 Offset, ULONG Length, + BOOLEAN WriteToEndOfFile, BOOLEAN ConstrainedIo, + PULONG PBytesTransferred, FILE_INFO *FileInfo) + { + return STATUS_INVALID_DEVICE_REQUEST; + } + virtual NTSTATUS Flush( + const FILE_CONTEXT *FileContext, + FILE_INFO *FileInfo) + { + return STATUS_INVALID_DEVICE_REQUEST; + } + virtual NTSTATUS GetFileInfo( + const FILE_CONTEXT *FileContext, + FILE_INFO *FileInfo) + { + return STATUS_INVALID_DEVICE_REQUEST; + } + virtual NTSTATUS SetBasicInfo( + const FILE_CONTEXT *FileContext, UINT32 FileAttributes, + UINT64 CreationTime, UINT64 LastAccessTime, UINT64 LastWriteTime, UINT64 ChangeTime, + FILE_INFO *FileInfo) + { + return STATUS_INVALID_DEVICE_REQUEST; + } + virtual NTSTATUS SetFileSize( + const FILE_CONTEXT *FileContext, UINT64 NewSize, BOOLEAN SetAllocationSize, + FILE_INFO *FileInfo) + { + return STATUS_INVALID_DEVICE_REQUEST; + } + virtual NTSTATUS CanDelete( + const FILE_CONTEXT *FileContext, PWSTR FileName) + { + return STATUS_INVALID_DEVICE_REQUEST; + } + virtual NTSTATUS Rename( + const FILE_CONTEXT *FileContext, + PWSTR FileName, PWSTR NewFileName, BOOLEAN ReplaceIfExists) + { + return STATUS_INVALID_DEVICE_REQUEST; + } + virtual NTSTATUS GetSecurity( + const FILE_CONTEXT *FileContext, + PSECURITY_DESCRIPTOR SecurityDescriptor, SIZE_T *PSecurityDescriptorSize) + { + return STATUS_INVALID_DEVICE_REQUEST; + } + virtual NTSTATUS SetSecurity( + const FILE_CONTEXT *FileContext, + SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR ModificationDescriptor) + { + return STATUS_INVALID_DEVICE_REQUEST; + } + virtual NTSTATUS ReadDirectory( + const FILE_CONTEXT *FileContext, PWSTR Pattern, PWSTR Marker, + PVOID Buffer, ULONG Length, PULONG PBytesTransferred) + { + 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(_FileSystem, GetReparsePointByName, 0, + 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( + const FILE_CONTEXT *FileContext, + PWSTR FileName, PVOID Buffer, PSIZE_T PSize) + { + return STATUS_INVALID_DEVICE_REQUEST; + } + virtual NTSTATUS SetReparsePoint( + const FILE_CONTEXT *FileContext, + PWSTR FileName, PVOID Buffer, SIZE_T Size) + { + return STATUS_INVALID_DEVICE_REQUEST; + } + virtual NTSTATUS DeleteReparsePoint( + const FILE_CONTEXT *FileContext, + PWSTR FileName, PVOID Buffer, SIZE_T Size) + { + return STATUS_INVALID_DEVICE_REQUEST; + } + virtual NTSTATUS GetStreamInfo( + const FILE_CONTEXT *FileContext, PVOID Buffer, ULONG Length, + PULONG PBytesTransferred) + { + return STATUS_INVALID_DEVICE_REQUEST; + } + +private: + /* FSP_FILE_SYSTEM_INTERFACE */ + static NTSTATUS GetVolumeInfo(FSP_FILE_SYSTEM *FileSystem0, + VOLUME_INFO *VolumeInfo) + { + FileSystem *self = (FileSystem *)FileSystem0->UserContext; + return self->GetVolumeInfo(VolumeInfo); + } + static NTSTATUS SetVolumeLabel_(FSP_FILE_SYSTEM *FileSystem0, + PWSTR VolumeLabel, + VOLUME_INFO *VolumeInfo) + { + FileSystem *self = (FileSystem *)FileSystem0->UserContext; + return self->SetVolumeLabel_(VolumeLabel, VolumeInfo); + } + static NTSTATUS GetSecurityByName(FSP_FILE_SYSTEM *FileSystem0, + PWSTR FileName, PUINT32 PFileAttributes/* or ReparsePointIndex */, + PSECURITY_DESCRIPTOR SecurityDescriptor, SIZE_T *PSecurityDescriptorSize) + { + FileSystem *self = (FileSystem *)FileSystem0->UserContext; + 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, FILE_INFO *FileInfo) + { + FileSystem *self = (FileSystem *)FileSystem0->UserContext; + FILE_CONTEXT FileContext; + NTSTATUS Result = self->Create( + FileName, CreateOptions, GrantedAccess, FileAttributes, SecurityDescriptor, AllocationSize, + &FileContext, FspFileSystemGetOpenFileInfo(FileInfo)); + ((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext = (UINT64)(UINT_PTR)FileContext.FileNode; + ((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext2 = (UINT64)(UINT_PTR)FileContext.FileDesc; + return Result; + } + static NTSTATUS Open(FSP_FILE_SYSTEM *FileSystem0, + PWSTR FileName, UINT32 CreateOptions, UINT32 GrantedAccess, + PVOID *FullContext, FILE_INFO *FileInfo) + { + FileSystem *self = (FileSystem *)FileSystem0->UserContext; + FILE_CONTEXT FileContext; + NTSTATUS Result = self->Open( + FileName, CreateOptions, GrantedAccess, + &FileContext, FspFileSystemGetOpenFileInfo(FileInfo)); + ((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext = (UINT64)(UINT_PTR)FileContext.FileNode; + ((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext2 = (UINT64)(UINT_PTR)FileContext.FileDesc; + return Result; + } + static NTSTATUS Overwrite(FSP_FILE_SYSTEM *FileSystem0, + PVOID FullContext, UINT32 FileAttributes, BOOLEAN ReplaceFileAttributes, UINT64 AllocationSize, + FILE_INFO *FileInfo) + { + FileSystem *self = (FileSystem *)FileSystem0->UserContext; + FILE_CONTEXT FileContext; + FileContext.FileNode = (PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext; + FileContext.FileDesc = (PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext2; + return self->Overwrite(&FileContext, FileAttributes, ReplaceFileAttributes, AllocationSize, + FileInfo); + } + static VOID Cleanup(FSP_FILE_SYSTEM *FileSystem0, + PVOID FullContext, PWSTR FileName, ULONG Flags) + { + FileSystem *self = (FileSystem *)FileSystem0->UserContext; + FILE_CONTEXT FileContext; + FileContext.FileNode = (PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext; + FileContext.FileDesc = (PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext2; + return self->Cleanup(&FileContext, FileName, (CLEANUP_FLAGS)Flags); + } + static VOID Close(FSP_FILE_SYSTEM *FileSystem0, + PVOID FullContext) + { + FileSystem *self = (FileSystem *)FileSystem0->UserContext; + FILE_CONTEXT FileContext; + FileContext.FileNode = (PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext; + FileContext.FileDesc = (PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext2; + return self->Close(&FileContext); + } + static NTSTATUS Read(FSP_FILE_SYSTEM *FileSystem0, + PVOID FullContext, PVOID Buffer, UINT64 Offset, ULONG Length, + PULONG PBytesTransferred) + { + FileSystem *self = (FileSystem *)FileSystem0->UserContext; + FILE_CONTEXT FileContext; + FileContext.FileNode = (PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext; + FileContext.FileDesc = (PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext2; + return self->Read(&FileContext, 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, FILE_INFO *FileInfo) + { + FileSystem *self = (FileSystem *)FileSystem0->UserContext; + FILE_CONTEXT FileContext; + FileContext.FileNode = (PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext; + FileContext.FileDesc = (PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext2; + return self->Write(&FileContext, Buffer, Offset, Length, WriteToEndOfFile, ConstrainedIo, + PBytesTransferred, FileInfo); + } + static NTSTATUS Flush(FSP_FILE_SYSTEM *FileSystem0, + PVOID FullContext, + FILE_INFO *FileInfo) + { + FileSystem *self = (FileSystem *)FileSystem0->UserContext; + FILE_CONTEXT FileContext; + FileContext.FileNode = (PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext; + FileContext.FileDesc = (PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext2; + return self->Flush(&FileContext, FileInfo); + } + static NTSTATUS GetFileInfo(FSP_FILE_SYSTEM *FileSystem0, + PVOID FullContext, + FILE_INFO *FileInfo) + { + FileSystem *self = (FileSystem *)FileSystem0->UserContext; + FILE_CONTEXT FileContext; + FileContext.FileNode = (PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext; + FileContext.FileDesc = (PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext2; + return self->GetFileInfo(&FileContext, FileInfo); + } + static NTSTATUS SetBasicInfo(FSP_FILE_SYSTEM *FileSystem0, + PVOID FullContext, UINT32 FileAttributes, + UINT64 CreationTime, UINT64 LastAccessTime, UINT64 LastWriteTime, UINT64 ChangeTime, + FILE_INFO *FileInfo) + { + FileSystem *self = (FileSystem *)FileSystem0->UserContext; + FILE_CONTEXT FileContext; + FileContext.FileNode = (PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext; + FileContext.FileDesc = (PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext2; + return self->SetBasicInfo(&FileContext, FileAttributes, + CreationTime, LastAccessTime, LastWriteTime, ChangeTime, + FileInfo); + } + static NTSTATUS SetFileSize(FSP_FILE_SYSTEM *FileSystem0, + PVOID FullContext, UINT64 NewSize, BOOLEAN SetAllocationSize, + FILE_INFO *FileInfo) + { + FileSystem *self = (FileSystem *)FileSystem0->UserContext; + FILE_CONTEXT FileContext; + FileContext.FileNode = (PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext; + FileContext.FileDesc = (PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext2; + return self->SetFileSize(&FileContext, NewSize, SetAllocationSize, FileInfo); + } + static NTSTATUS CanDelete(FSP_FILE_SYSTEM *FileSystem0, + PVOID FullContext, PWSTR FileName) + { + FileSystem *self = (FileSystem *)FileSystem0->UserContext; + FILE_CONTEXT FileContext; + FileContext.FileNode = (PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext; + FileContext.FileDesc = (PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext2; + return self->CanDelete(&FileContext, FileName); + } + static NTSTATUS Rename(FSP_FILE_SYSTEM *FileSystem0, + PVOID FullContext, + PWSTR FileName, PWSTR NewFileName, BOOLEAN ReplaceIfExists) + { + FileSystem *self = (FileSystem *)FileSystem0->UserContext; + FILE_CONTEXT FileContext; + FileContext.FileNode = (PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext; + FileContext.FileDesc = (PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext2; + return self->Rename(&FileContext, FileName, NewFileName, ReplaceIfExists); + } + static NTSTATUS GetSecurity(FSP_FILE_SYSTEM *FileSystem0, + PVOID FullContext, + PSECURITY_DESCRIPTOR SecurityDescriptor, SIZE_T *PSecurityDescriptorSize) + { + FileSystem *self = (FileSystem *)FileSystem0->UserContext; + FILE_CONTEXT FileContext; + FileContext.FileNode = (PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext; + FileContext.FileDesc = (PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext2; + return self->GetSecurity(&FileContext, SecurityDescriptor, PSecurityDescriptorSize); + } + static NTSTATUS SetSecurity(FSP_FILE_SYSTEM *FileSystem0, + PVOID FullContext, + SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR ModificationDescriptor) + { + FileSystem *self = (FileSystem *)FileSystem0->UserContext; + FILE_CONTEXT FileContext; + FileContext.FileNode = (PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext; + FileContext.FileDesc = (PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext2; + return self->SetSecurity(&FileContext, SecurityInformation, ModificationDescriptor); + } + static NTSTATUS ReadDirectory(FSP_FILE_SYSTEM *FileSystem0, + PVOID FullContext, PWSTR Pattern, PWSTR Marker, + PVOID Buffer, ULONG Length, PULONG PBytesTransferred) + { + FileSystem *self = (FileSystem *)FileSystem0->UserContext; + FILE_CONTEXT FileContext; + FileContext.FileNode = (PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext; + FileContext.FileDesc = (PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext2; + return self->ReadDirectory(&FileContext, 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) + { + FileSystem *self = (FileSystem *)FileSystem0->UserContext; + return self->ResolveReparsePoints(FileName, ReparsePointIndex, ResolveLastPathComponent, + PIoStatus, Buffer, PSize); + } + static NTSTATUS GetReparsePointByName( + FSP_FILE_SYSTEM *FileSystem0, PVOID Context, + PWSTR FileName, BOOLEAN IsDirectory, PVOID Buffer, PSIZE_T PSize) + { + FileSystem *self = (FileSystem *)FileSystem0->UserContext; + return self->GetReparsePointByName(FileName, IsDirectory, Buffer, PSize); + } + static NTSTATUS GetReparsePoint(FSP_FILE_SYSTEM *FileSystem0, + PVOID FullContext, + PWSTR FileName, PVOID Buffer, PSIZE_T PSize) + { + FileSystem *self = (FileSystem *)FileSystem0->UserContext; + FILE_CONTEXT FileContext; + FileContext.FileNode = (PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext; + FileContext.FileDesc = (PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext2; + return self->GetReparsePoint(&FileContext, FileName, Buffer, PSize); + } + static NTSTATUS SetReparsePoint(FSP_FILE_SYSTEM *FileSystem0, + PVOID FullContext, + PWSTR FileName, PVOID Buffer, SIZE_T Size) + { + FileSystem *self = (FileSystem *)FileSystem0->UserContext; + FILE_CONTEXT FileContext; + FileContext.FileNode = (PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext; + FileContext.FileDesc = (PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext2; + return self->SetReparsePoint(&FileContext, FileName, Buffer, Size); + } + static NTSTATUS DeleteReparsePoint(FSP_FILE_SYSTEM *FileSystem0, + PVOID FullContext, + PWSTR FileName, PVOID Buffer, SIZE_T Size) + { + FileSystem *self = (FileSystem *)FileSystem0->UserContext; + FILE_CONTEXT FileContext; + FileContext.FileNode = (PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext; + FileContext.FileDesc = (PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext2; + return self->DeleteReparsePoint(&FileContext, FileName, Buffer, Size); + } + static NTSTATUS GetStreamInfo(FSP_FILE_SYSTEM *FileSystem0, + PVOID FullContext, PVOID Buffer, ULONG Length, + PULONG PBytesTransferred) + { + FileSystem *self = (FileSystem *)FileSystem0->UserContext; + FILE_CONTEXT FileContext; + FileContext.FileNode = (PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext; + FileContext.FileDesc = (PVOID)(UINT_PTR)((FSP_FSCTL_TRANSACT_FULL_CONTEXT *)FullContext)->UserContext2; + return self->GetStreamInfo(&FileContext, 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 */ + FileSystem(const FileSystem &); + FileSystem &operator=(const FileSystem &); + +private: + VOLUME_PARAMS _VolumeParams; + FSP_FILE_SYSTEM *_FileSystem; +}; + +} + +#endif