diff --git a/src/dotnet/FileSystem.cs b/src/dotnet/FileSystem.cs index c3d97132..7b3fb5de 100644 --- a/src/dotnet/FileSystem.cs +++ b/src/dotnet/FileSystem.cs @@ -26,6 +26,27 @@ namespace Fsp public partial class FileSystem : IDisposable { + /* 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; + } + /* ctor/dtor */ public FileSystem() { @@ -177,6 +198,70 @@ namespace Fsp } /* helpers */ + public Int32 SeekableReadDirectory( + Object FileNode, + Object FileDesc, + String Pattern, + String Marker, + IntPtr Buffer, + UInt32 Length, + out UInt32 PBytesTransferred) + { + Object Context = null; + String FileName; + DirInfo DirInfo = default(DirInfo); + PBytesTransferred = 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 PBytesTransferred)) + break; + } + return STATUS_SUCCESS; + } + public Int32 BufferedReadDirectory( + DirectoryBuffer DirectoryBuffer, + Object FileNode, + Object FileDesc, + String Pattern, + String Marker, + IntPtr Buffer, + UInt32 Length, + out UInt32 PBytesTransferred) + { + Object Context = null; + String FileName; + DirInfo DirInfo = default(DirInfo); + Int32 DirBufferResult = STATUS_SUCCESS; + PBytesTransferred = 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) + { + PBytesTransferred = default(UInt32); + return DirBufferResult; + } + Api.FspFileSystemReadDirectoryBuffer(ref DirectoryBuffer.DirBuffer, + Marker, Buffer, Length, out PBytesTransferred); + return STATUS_SUCCESS; + } public static Int32 NtStatusFromWin32(UInt32 Error) { return Api.FspNtStatusFromWin32(Error); @@ -380,6 +465,19 @@ namespace Fsp PBytesTransferred = default(UInt32); return STATUS_INVALID_DEVICE_REQUEST; } + protected 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; + } protected virtual Int32 ResolveReparsePoints( String FileName, UInt32 ReparsePointIndex, diff --git a/src/dotnet/Interop.cs b/src/dotnet/Interop.cs index dd42f7cc..5040cfc4 100644 --- a/src/dotnet/Interop.cs +++ b/src/dotnet/Interop.cs @@ -152,10 +152,26 @@ namespace Fsp.Interop [StructLayout(LayoutKind.Sequential)] internal struct DirInfo { + internal const int FileNameBufSize = 255; + internal UInt16 Size; internal FileInfo FileInfo; internal unsafe fixed Byte Padding[24]; //internal unsafe fixed UInt16 FileNameBuf[]; + internal unsafe fixed UInt16 FileNameBuf[FileNameBufSize]; + + public unsafe void SetFileNameBuf(String Value) + { + fixed (UInt16 *P = FileNameBuf) + { + int Size = Value.Length; + if (Size > FileNameBufSize) + Size = FileNameBufSize; + for (int I = 0; Size > I; I++) + P[I] = Value[I]; + this.Size = (UInt16)(sizeof(DirInfo) + Size); + } + } } [StructLayout(LayoutKind.Sequential)] @@ -424,6 +440,12 @@ namespace Fsp.Interop internal delegate Int32 FspFileSystemStopDispatcher( IntPtr FileSystem); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Boolean FspFileSystemAddDirInfo( + IntPtr DirInfo, + IntPtr Buffer, + UInt32 Length, + out UInt32 PBytesTransferred); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate Int32 FspFileSystemFindReparsePoint( IntPtr FileSystem, GetReparsePointByName GetReparsePointByName, @@ -441,6 +463,41 @@ namespace Fsp.Interop out IoStatusBlock PIoStatus, IntPtr Buffer, ref UIntPtr PSize); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Int32 FspFileSystemCanReplaceReparsePoint( + IntPtr CurrentReparseData, + UIntPtr CurrentReparseDataSize, + IntPtr ReplaceReparseData, + UIntPtr ReplaceReparseDataSize); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Boolean FspFileSystemAddStreamInfo( + IntPtr StreamInfo, + IntPtr Buffer, + UInt32 Length, + out UInt32 PBytesTransferred); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Boolean FspFileSystemAcquireDirectoryBuffer( + ref IntPtr PDirBuffer, + Boolean Reset, + out Int32 PResult); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Boolean FspFileSystemFillDirectoryBuffer( + ref IntPtr PDirBuffer, + ref DirInfo DirInfo, + out Int32 PResult); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void FspFileSystemReleaseDirectoryBuffer( + ref IntPtr PDirBuffer); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void FspFileSystemReadDirectoryBuffer( + ref IntPtr PDirBuffer, + [MarshalAs(UnmanagedType.LPWStr)] String Marker, + IntPtr Buffer, + UInt32 Length, + out UInt32 PBytesTransferred); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void FspFileSystemDeleteDirectoryBuffer( + ref IntPtr PDirBuffer); /* Service */ [UnmanagedFunctionPointer(CallingConvention.Cdecl)] @@ -528,9 +585,16 @@ namespace Fsp.Interop internal static Proto.FspFileSystemRemoveMountPoint FspFileSystemRemoveMountPoint; internal static Proto.FspFileSystemStartDispatcher FspFileSystemStartDispatcher; internal static Proto.FspFileSystemStopDispatcher FspFileSystemStopDispatcher; + internal static Proto.FspFileSystemAddDirInfo _FspFileSystemAddDirInfo; internal static Proto.FspFileSystemFindReparsePoint FspFileSystemFindReparsePoint; internal static Proto.FspFileSystemResolveReparsePoints FspFileSystemResolveReparsePoints; - internal static Proto.FspVersion FspVersion; + internal static Proto.FspFileSystemCanReplaceReparsePoint FspFileSystemCanReplaceReparsePoint; + internal static Proto.FspFileSystemAddStreamInfo FspFileSystemAddStreamInfo; + internal static Proto.FspFileSystemAcquireDirectoryBuffer FspFileSystemAcquireDirectoryBuffer; + internal static Proto.FspFileSystemFillDirectoryBuffer FspFileSystemFillDirectoryBuffer; + internal static Proto.FspFileSystemReleaseDirectoryBuffer FspFileSystemReleaseDirectoryBuffer; + internal static Proto.FspFileSystemReadDirectoryBuffer FspFileSystemReadDirectoryBuffer; + internal static Proto.FspFileSystemDeleteDirectoryBuffer FspFileSystemDeleteDirectoryBuffer; internal static Proto.FspServiceCreate FspServiceCreate; internal static Proto.FspServiceDelete FspServiceDelete; internal static Proto.FspServiceAllowConsoleMode FspServiceAllowConsoleMode; @@ -540,6 +604,7 @@ namespace Fsp.Interop internal static Proto.FspServiceLoop FspServiceLoop; internal static Proto.FspServiceStop FspServiceStop; internal static Proto.FspServiceLog FspServiceLog; + internal static Proto.FspVersion FspVersion; internal static Proto.FspNtStatusFromWin32 FspNtStatusFromWin32; internal static Proto.FspWin32FromNtStatus FspWin32FromNtStatus; internal static Proto.FspDebugLogSetHandle FspDebugLogSetHandle; @@ -557,6 +622,15 @@ namespace Fsp.Interop else return _FspFileSystemSetMountPointEx(FileSystem, MountPoint, IntPtr.Zero); } + internal static unsafe Boolean FspFileSystemAddDirInfo( + ref DirInfo DirInfo, + IntPtr Buffer, + UInt32 Length, + out UInt32 PBytesTransferred) + { + fixed (DirInfo *P = &DirInfo) + return _FspFileSystemAddDirInfo((IntPtr)P, Buffer, Length, out PBytesTransferred); + } internal unsafe static Object GetUserContext( IntPtr NativePtr) @@ -729,8 +803,16 @@ namespace Fsp.Interop FspFileSystemRemoveMountPoint = GetEntryPoint(Module); FspFileSystemStartDispatcher = GetEntryPoint(Module); FspFileSystemStopDispatcher = GetEntryPoint(Module); + _FspFileSystemAddDirInfo = GetEntryPoint(Module); FspFileSystemFindReparsePoint = GetEntryPoint(Module); FspFileSystemResolveReparsePoints = GetEntryPoint(Module); + FspFileSystemCanReplaceReparsePoint = GetEntryPoint(Module); + FspFileSystemAddStreamInfo = GetEntryPoint(Module); + FspFileSystemAcquireDirectoryBuffer = GetEntryPoint(Module); + FspFileSystemFillDirectoryBuffer = GetEntryPoint(Module); + FspFileSystemReleaseDirectoryBuffer = GetEntryPoint(Module); + FspFileSystemReadDirectoryBuffer = GetEntryPoint(Module); + FspFileSystemDeleteDirectoryBuffer = GetEntryPoint(Module); FspServiceCreate = GetEntryPoint(Module); FspServiceDelete = GetEntryPoint(Module); FspServiceAllowConsoleMode = GetEntryPoint(Module);