mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-22 08:23:05 -05:00
468 lines
14 KiB
C#
468 lines
14 KiB
C#
/**
|
|
* @file dotnet/FileSystemBase.cs
|
|
*
|
|
* @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.
|
|
*/
|
|
|
|
using System;
|
|
using System.Runtime.InteropServices;
|
|
using System.Security.AccessControl;
|
|
|
|
using Fsp.Interop;
|
|
|
|
namespace Fsp
|
|
{
|
|
|
|
public partial class FileSystemBase
|
|
{
|
|
/* types */
|
|
public class DirectoryBuffer : IDisposable
|
|
{
|
|
~DirectoryBuffer()
|
|
{
|
|
Dispose(false);
|
|
}
|
|
public void Dispose()
|
|
{
|
|
lock (this)
|
|
Dispose(true);
|
|
GC.SuppressFinalize(true);
|
|
}
|
|
protected virtual void Dispose(bool disposing)
|
|
{
|
|
Api.FspFileSystemDeleteDirectoryBuffer(ref DirBuffer);
|
|
}
|
|
|
|
internal IntPtr DirBuffer;
|
|
}
|
|
|
|
/* operations */
|
|
public virtual Int32 ExceptionHandler(Exception ex)
|
|
{
|
|
return STATUS_UNEXPECTED_IO_ERROR;
|
|
}
|
|
public virtual Int32 Init(Object Host)
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
public virtual Int32 Mounted(Object Host)
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
public virtual void Unmounted(Object Host)
|
|
{
|
|
}
|
|
public virtual Int32 GetVolumeInfo(
|
|
out VolumeInfo VolumeInfo)
|
|
{
|
|
VolumeInfo = default(VolumeInfo);
|
|
return STATUS_INVALID_DEVICE_REQUEST;
|
|
}
|
|
public virtual Int32 SetVolumeLabel(
|
|
String VolumeLabel,
|
|
out VolumeInfo VolumeInfo)
|
|
{
|
|
VolumeInfo = default(VolumeInfo);
|
|
return STATUS_INVALID_DEVICE_REQUEST;
|
|
}
|
|
public virtual Int32 GetSecurityByName(
|
|
String FileName,
|
|
out UInt32 FileAttributes/* or ReparsePointIndex */,
|
|
ref Byte[] SecurityDescriptor)
|
|
{
|
|
FileAttributes = default(UInt32);
|
|
return STATUS_INVALID_DEVICE_REQUEST;
|
|
}
|
|
public virtual Int32 Create(
|
|
String FileName,
|
|
UInt32 CreateOptions,
|
|
UInt32 GrantedAccess,
|
|
UInt32 FileAttributes,
|
|
Byte[] SecurityDescriptor,
|
|
UInt64 AllocationSize,
|
|
out Object FileNode,
|
|
out Object FileDesc,
|
|
out FileInfo FileInfo,
|
|
out String NormalizedName)
|
|
{
|
|
FileNode = default(Object);
|
|
FileDesc = default(Object);
|
|
FileInfo = default(FileInfo);
|
|
NormalizedName = default(String);
|
|
return STATUS_INVALID_DEVICE_REQUEST;
|
|
}
|
|
public virtual Int32 Open(
|
|
String FileName,
|
|
UInt32 CreateOptions,
|
|
UInt32 GrantedAccess,
|
|
out Object FileNode,
|
|
out Object FileDesc,
|
|
out FileInfo FileInfo,
|
|
out String NormalizedName)
|
|
{
|
|
FileNode = default(Object);
|
|
FileDesc = default(Object);
|
|
FileInfo = default(FileInfo);
|
|
NormalizedName = default(String);
|
|
return STATUS_INVALID_DEVICE_REQUEST;
|
|
}
|
|
public virtual Int32 Overwrite(
|
|
Object FileNode,
|
|
Object FileDesc,
|
|
UInt32 FileAttributes,
|
|
Boolean ReplaceFileAttributes,
|
|
UInt64 AllocationSize,
|
|
out FileInfo FileInfo)
|
|
{
|
|
FileInfo = default(FileInfo);
|
|
return STATUS_INVALID_DEVICE_REQUEST;
|
|
}
|
|
public virtual void Cleanup(
|
|
Object FileNode,
|
|
Object FileDesc,
|
|
String FileName,
|
|
UInt32 Flags)
|
|
{
|
|
}
|
|
public virtual void Close(
|
|
Object FileNode,
|
|
Object FileDesc)
|
|
{
|
|
}
|
|
public virtual Int32 Read(
|
|
Object FileNode,
|
|
Object FileDesc,
|
|
IntPtr Buffer,
|
|
UInt64 Offset,
|
|
UInt32 Length,
|
|
out UInt32 BytesTransferred)
|
|
{
|
|
BytesTransferred = default(UInt32);
|
|
return STATUS_INVALID_DEVICE_REQUEST;
|
|
}
|
|
public virtual Int32 Write(
|
|
Object FileNode,
|
|
Object FileDesc,
|
|
IntPtr Buffer,
|
|
UInt64 Offset,
|
|
UInt32 Length,
|
|
Boolean WriteToEndOfFile,
|
|
Boolean ConstrainedIo,
|
|
out UInt32 BytesTransferred,
|
|
out FileInfo FileInfo)
|
|
{
|
|
BytesTransferred = default(UInt32);
|
|
FileInfo = default(FileInfo);
|
|
return STATUS_INVALID_DEVICE_REQUEST;
|
|
}
|
|
public virtual Int32 Flush(
|
|
Object FileNode,
|
|
Object FileDesc,
|
|
out FileInfo FileInfo)
|
|
{
|
|
FileInfo = default(FileInfo);
|
|
return STATUS_INVALID_DEVICE_REQUEST;
|
|
}
|
|
public virtual Int32 GetFileInfo(
|
|
Object FileNode,
|
|
Object FileDesc,
|
|
out FileInfo FileInfo)
|
|
{
|
|
FileInfo = default(FileInfo);
|
|
return STATUS_INVALID_DEVICE_REQUEST;
|
|
}
|
|
public virtual Int32 SetBasicInfo(
|
|
Object FileNode,
|
|
Object FileDesc,
|
|
UInt32 FileAttributes,
|
|
UInt64 CreationTime,
|
|
UInt64 LastAccessTime,
|
|
UInt64 LastWriteTime,
|
|
UInt64 ChangeTime,
|
|
out FileInfo FileInfo)
|
|
{
|
|
FileInfo = default(FileInfo);
|
|
return STATUS_INVALID_DEVICE_REQUEST;
|
|
}
|
|
public virtual Int32 SetFileSize(
|
|
Object FileNode,
|
|
Object FileDesc,
|
|
UInt64 NewSize,
|
|
Boolean SetAllocationSize,
|
|
out FileInfo FileInfo)
|
|
{
|
|
FileInfo = default(FileInfo);
|
|
return STATUS_INVALID_DEVICE_REQUEST;
|
|
}
|
|
public virtual Int32 CanDelete(
|
|
Object FileNode,
|
|
Object FileDesc,
|
|
String FileName)
|
|
{
|
|
return STATUS_INVALID_DEVICE_REQUEST;
|
|
}
|
|
public virtual Int32 Rename(
|
|
Object FileNode,
|
|
Object FileDesc,
|
|
String FileName,
|
|
String NewFileName,
|
|
Boolean ReplaceIfExists)
|
|
{
|
|
return STATUS_INVALID_DEVICE_REQUEST;
|
|
}
|
|
public virtual Int32 GetSecurity(
|
|
Object FileNode,
|
|
Object FileDesc,
|
|
ref Byte[] SecurityDescriptor)
|
|
{
|
|
return STATUS_INVALID_DEVICE_REQUEST;
|
|
}
|
|
public virtual Int32 SetSecurity(
|
|
Object FileNode,
|
|
Object FileDesc,
|
|
AccessControlSections Sections,
|
|
Byte[] SecurityDescriptor)
|
|
{
|
|
return STATUS_INVALID_DEVICE_REQUEST;
|
|
}
|
|
public virtual Int32 ReadDirectory(
|
|
Object FileNode,
|
|
Object FileDesc,
|
|
String Pattern,
|
|
String Marker,
|
|
IntPtr Buffer,
|
|
UInt32 Length,
|
|
out UInt32 BytesTransferred)
|
|
{
|
|
return SeekableReadDirectory(FileNode, FileDesc, Pattern, Marker, Buffer, Length,
|
|
out BytesTransferred);
|
|
}
|
|
public virtual Boolean ReadDirectoryEntry(
|
|
Object FileNode,
|
|
Object FileDesc,
|
|
String Pattern,
|
|
String Marker,
|
|
ref Object Context,
|
|
out String FileName,
|
|
out FileInfo FileInfo)
|
|
{
|
|
FileName = default(String);
|
|
FileInfo = default(FileInfo);
|
|
return false;
|
|
}
|
|
public virtual Int32 ResolveReparsePoints(
|
|
String FileName,
|
|
UInt32 ReparsePointIndex,
|
|
Boolean ResolveLastPathComponent,
|
|
out IoStatusBlock IoStatus,
|
|
IntPtr Buffer,
|
|
IntPtr PSize)
|
|
{
|
|
GCHandle Handle = GCHandle.Alloc(this, GCHandleType.Normal);
|
|
try
|
|
{
|
|
return Api.FspFileSystemResolveReparsePoints(
|
|
IntPtr.Zero,
|
|
GetReparsePointByName,
|
|
(IntPtr)Handle,
|
|
FileName,
|
|
ReparsePointIndex,
|
|
ResolveLastPathComponent,
|
|
out IoStatus,
|
|
Buffer,
|
|
PSize);
|
|
}
|
|
finally
|
|
{
|
|
Handle.Free();
|
|
}
|
|
}
|
|
public virtual Int32 GetReparsePointByName(
|
|
String FileName,
|
|
Boolean IsDirectory,
|
|
ref Byte[] ReparsePoint)
|
|
{
|
|
return STATUS_INVALID_DEVICE_REQUEST;
|
|
}
|
|
public virtual Int32 GetReparsePoint(
|
|
Object FileNode,
|
|
Object FileDesc,
|
|
String FileName,
|
|
ref Byte[] ReparsePoint)
|
|
{
|
|
return STATUS_INVALID_DEVICE_REQUEST;
|
|
}
|
|
public virtual Int32 SetReparsePoint(
|
|
Object FileNode,
|
|
Object FileDesc,
|
|
String FileName,
|
|
Byte[] ReparsePoint)
|
|
{
|
|
return STATUS_INVALID_DEVICE_REQUEST;
|
|
}
|
|
public virtual Int32 DeleteReparsePoint(
|
|
Object FileNode,
|
|
Object FileDesc,
|
|
String FileName,
|
|
Byte[] ReparsePoint)
|
|
{
|
|
return STATUS_INVALID_DEVICE_REQUEST;
|
|
}
|
|
public virtual Int32 GetStreamInfo(
|
|
Object FileNode,
|
|
Object FileDesc,
|
|
IntPtr Buffer,
|
|
UInt32 Length,
|
|
out UInt32 BytesTransferred)
|
|
{
|
|
BytesTransferred = default(UInt32);
|
|
return STATUS_INVALID_DEVICE_REQUEST;
|
|
}
|
|
|
|
/* helpers */
|
|
public static Int32 NtStatusFromWin32(UInt32 Error)
|
|
{
|
|
return Api.FspNtStatusFromWin32(Error);
|
|
}
|
|
public static UInt32 Win32FromNtStatus(Int32 Status)
|
|
{
|
|
return Api.FspWin32FromNtStatus(Status);
|
|
}
|
|
public Int32 SeekableReadDirectory(
|
|
Object FileNode,
|
|
Object FileDesc,
|
|
String Pattern,
|
|
String Marker,
|
|
IntPtr Buffer,
|
|
UInt32 Length,
|
|
out UInt32 BytesTransferred)
|
|
{
|
|
Object Context = null;
|
|
String FileName;
|
|
DirInfo DirInfo = default(DirInfo);
|
|
BytesTransferred = default(UInt32);
|
|
while (ReadDirectoryEntry(FileNode, FileDesc, Pattern, Marker,
|
|
ref Context, out FileName, out DirInfo.FileInfo))
|
|
{
|
|
DirInfo.SetFileNameBuf(FileName);
|
|
if (!Api.FspFileSystemAddDirInfo(ref DirInfo, Buffer, Length,
|
|
out BytesTransferred))
|
|
break;
|
|
}
|
|
return STATUS_SUCCESS;
|
|
}
|
|
public Int32 BufferedReadDirectory(
|
|
DirectoryBuffer DirectoryBuffer,
|
|
Object FileNode,
|
|
Object FileDesc,
|
|
String Pattern,
|
|
String Marker,
|
|
IntPtr Buffer,
|
|
UInt32 Length,
|
|
out UInt32 BytesTransferred)
|
|
{
|
|
Object Context = null;
|
|
String FileName;
|
|
DirInfo DirInfo = default(DirInfo);
|
|
Int32 DirBufferResult = STATUS_SUCCESS;
|
|
BytesTransferred = default(UInt32);
|
|
if (Api.FspFileSystemAcquireDirectoryBuffer(ref DirectoryBuffer.DirBuffer, null == Marker,
|
|
out DirBufferResult))
|
|
try
|
|
{
|
|
while (ReadDirectoryEntry(FileNode, FileDesc, Pattern, Marker,
|
|
ref Context, out FileName, out DirInfo.FileInfo))
|
|
{
|
|
DirInfo.SetFileNameBuf(FileName);
|
|
if (!Api.FspFileSystemFillDirectoryBuffer(
|
|
ref DirectoryBuffer.DirBuffer, ref DirInfo, out DirBufferResult))
|
|
break;
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
Api.FspFileSystemReleaseDirectoryBuffer(ref DirectoryBuffer.DirBuffer);
|
|
}
|
|
if (0 > DirBufferResult)
|
|
{
|
|
BytesTransferred = default(UInt32);
|
|
return DirBufferResult;
|
|
}
|
|
Api.FspFileSystemReadDirectoryBuffer(ref DirectoryBuffer.DirBuffer,
|
|
Marker, Buffer, Length, out BytesTransferred);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
public Boolean FindReparsePoint(
|
|
String FileName,
|
|
out UInt32 ReparsePointIndex)
|
|
{
|
|
GCHandle Handle = GCHandle.Alloc(this, GCHandleType.Normal);
|
|
try
|
|
{
|
|
return Api.FspFileSystemFindReparsePoint(
|
|
IntPtr.Zero,
|
|
GetReparsePointByName,
|
|
(IntPtr)Handle,
|
|
FileName,
|
|
out ReparsePointIndex);
|
|
}
|
|
finally
|
|
{
|
|
Handle.Free();
|
|
}
|
|
}
|
|
public static UInt32 GetReparseTag(
|
|
Byte[] ReparseData)
|
|
{
|
|
return 0;
|
|
}
|
|
public static Int32 CanReplaceReparsePoint(
|
|
Byte[] CurrentReparseData,
|
|
Byte[] ReplaceReparseData)
|
|
{
|
|
// !!!: NOT IMPLEMENTED
|
|
return STATUS_SUCCESS;
|
|
}
|
|
private static Int32 GetReparsePointByName(
|
|
IntPtr FileSystem,
|
|
IntPtr Context,
|
|
String FileName,
|
|
Boolean IsDirectory,
|
|
IntPtr Buffer,
|
|
IntPtr PSize)
|
|
{
|
|
FileSystemBase self = (FileSystemBase)GCHandle.FromIntPtr(Context).Target;
|
|
try
|
|
{
|
|
Byte[] ReparsePointBytes;
|
|
Int32 Result;
|
|
ReparsePointBytes = null;
|
|
Result = self.GetReparsePointByName(
|
|
FileName,
|
|
IsDirectory,
|
|
ref ReparsePointBytes);
|
|
if (0 <= Result)
|
|
Result = Api.CopyReparsePoint(ReparsePointBytes, Buffer, PSize);
|
|
return Result;
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return self.ExceptionHandler(ex);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|