winfsp/src/dotnet/FileSystemBase.cs
2017-05-05 18:23:52 -07:00

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);
}
}
}
}