diff --git a/src/dotnet/FileSystemBase.cs b/src/dotnet/FileSystemBase.cs
index e66da75a..e208abd9 100644
--- a/src/dotnet/FileSystemBase.cs
+++ b/src/dotnet/FileSystemBase.cs
@@ -966,6 +966,49 @@ namespace Fsp
FileInfo = default(FileInfo);
return STATUS_INVALID_DEVICE_REQUEST;
}
+ ///
+ /// Processes a control code.
+ ///
+ ///
+ /// This function is called when a program uses the DeviceIoControl API.
+ ///
+ ///
+ /// The file node of the file or directory to be controled.
+ ///
+ ///
+ /// The file descriptor of the file or directory to be controled.
+ ///
+ ///
+ /// The control code for the operation. This code must have a DeviceType with bit
+ /// 0x8000 set and must have a TransferType of METHOD_BUFFERED.
+ ///
+ ///
+ /// Pointer to a buffer that contains the input data.
+ ///
+ ///
+ /// Input data length.
+ ///
+ ///
+ /// Pointer to a buffer that will receive the output data.
+ ///
+ ///
+ /// Output data length.
+ ///
+ ///
+ /// Receives the actual number of bytes transferred.
+ ///
+ /// STATUS_SUCCESS or error code.
+ public virtual Int32 Control(
+ Object FileNode,
+ Object FileDesc,
+ UInt32 ControlCode,
+ IntPtr InputBuffer, UInt32 InputBufferLength,
+ IntPtr OutputBuffer, UInt32 OutputBufferLength,
+ out UInt32 BytesTransferred)
+ {
+ BytesTransferred = default(UInt32);
+ return STATUS_INVALID_DEVICE_REQUEST;
+ }
/* helpers */
///
diff --git a/src/dotnet/FileSystemHost.cs b/src/dotnet/FileSystemHost.cs
index d98ad582..55a14c2c 100644
--- a/src/dotnet/FileSystemHost.cs
+++ b/src/dotnet/FileSystemHost.cs
@@ -1020,6 +1020,35 @@ namespace Fsp
return ExceptionHandler(FileSystem, ex);
}
}
+ private static Int32 Control(
+ IntPtr FileSystemPtr,
+ ref FullContext FullContext,
+ UInt32 ControlCode,
+ IntPtr InputBuffer, UInt32 InputBufferLength,
+ IntPtr OutputBuffer, UInt32 OutputBufferLength,
+ out UInt32 PBytesTransferred)
+ {
+ FileSystemBase FileSystem = (FileSystemBase)Api.GetUserContext(FileSystemPtr);
+ try
+ {
+ Object FileNode, FileDesc;
+ Api.GetFullContext(ref FullContext, out FileNode, out FileDesc);
+ return FileSystem.Control(
+ FileNode,
+ FileDesc,
+ ControlCode,
+ InputBuffer,
+ InputBufferLength,
+ OutputBuffer,
+ OutputBufferLength,
+ out PBytesTransferred);
+ }
+ catch (Exception ex)
+ {
+ PBytesTransferred = default(UInt32);
+ return ExceptionHandler(FileSystem, ex);
+ }
+ }
static FileSystemHost()
{
@@ -1048,6 +1077,7 @@ namespace Fsp
_FileSystemInterface.DeleteReparsePoint = DeleteReparsePoint;
_FileSystemInterface.GetStreamInfo = GetStreamInfo;
_FileSystemInterface.GetDirInfoByName = GetDirInfoByName;
+ _FileSystemInterface.Control = Control;
_FileSystemInterfacePtr = Marshal.AllocHGlobal(FileSystemInterface.Size);
Marshal.StructureToPtr(_FileSystemInterface, _FileSystemInterfacePtr, false);
diff --git a/src/dotnet/Interop.cs b/src/dotnet/Interop.cs
index c9a7c95b..c81e9b67 100644
--- a/src/dotnet/Interop.cs
+++ b/src/dotnet/Interop.cs
@@ -457,6 +457,14 @@ namespace Fsp.Interop
ref FullContext FullContext,
[MarshalAs(UnmanagedType.LPWStr)] String FileName,
out DirInfo DirInfo);
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ internal delegate Int32 Control(
+ IntPtr FileSystem,
+ ref FullContext FullContext,
+ UInt32 ControlCode,
+ IntPtr InputBuffer, UInt32 InputBufferLength,
+ IntPtr OutputBuffer, UInt32 OutputBufferLength,
+ out UInt32 PBytesTransferred);
}
internal static int Size = IntPtr.Size * 64;
@@ -486,7 +494,8 @@ namespace Fsp.Interop
internal Proto.DeleteReparsePoint DeleteReparsePoint;
internal Proto.GetStreamInfo GetStreamInfo;
internal Proto.GetDirInfoByName GetDirInfoByName;
- /* NTSTATUS (*Reserved[39])(); */
+ internal Proto.Control Control;
+ /* NTSTATUS (*Reserved[38])(); */
}
[SuppressUnmanagedCodeSecurity]