This event is fired when the filesystem receives the non-standard request (filesystem control code).
property OnFsctl : TCBFsctlEvent;
TCBFsctlEvent = procedure( Sender : TObject; FileInfo: TCBFileInfo; Code: LongWord; var InputBuffer; InputBufferLength: LongWord; var OutputBuffer; OutputBufferLength: LongWord; var BytesReturned: LongWord ) of object;
void (__stdcall *CBFsctlEvent)(void* Sender, CBFileInfo* FileInfo, DWORD Code, PVOID InputBuffer, DWORD InputBufferLength, PVOID OutputBuffer, DWORD OutputBufferLength, PDWORD BytesReturned );
typedef void (__closure *TCBFsctlEvent)( System::TObject* Sender, TCBFileInfo* FileInfo, unsigned Code, void *InputBuffer, unsigned long InputBufferLength, void *OutputBuffer, unsigned long OutputBufferLength, unsigned long &BytesReturned );
public __delegate void CBFsctlEvent( CBFSConnect^ Sender, CBFileInfo^ FileInfo, UInt32 Code, IntPtr InputBuffer, UInt32 InputBufferLength, IntPtr OutputBuffer, UInt32 OutputBufferLength, UInt32% BytesReturned );
public void CBFsctlEvent( CBFSConnect Sender, CBFileInfo FileInfo, UInt32 Code, IntPtr InputBuffer, UInt32 InputBufferLength, IntPtr OutputBuffer, UInt32 OutputBufferLength, UInt32% BytesReturned );
Sub CBFsctlEvent( ByVal Sender As CBFSConnect, ByVal FileInfo As CBFileInfo, ByVal Code As UInt32; ByVal InputBuffer as IntPtr; ByVal InputBufferLength as UInt32; ByVal OutputBuffer As IntPtr; ByVal OutputBufferLength as UInt32; ByRef BytesReturned as UInt32 )
void ICbFsFileEvents.onFsCtl( CBFSConnect sender, CBFileInfo fileInfo, int Code, byteArrayRef inputBuffer, int inputBufferLength, byteArrayRef outputBuffer, int outputBufferLength, intRef bytesReturned );
FSCTL (an abbreviation of file system input/output control) is a system call for file system-specific input/output operations and other operations which cannot be expressed by regular file system calls. It takes a parameter that holds a control request code; the effect of the call depends completely on the control request code.
This event is fired when a FSCTL request is passed to CBFS.
Control codes are composed of the function code and flags that describe how parameters are passed. Normally CBFS reserves function codes of 2400 to 4096 for application use and fires this event only for those control codes. If HandleAllFsctls property is set to true, then the event is fired for all FSCTLs, execept those ones that are processed by CBFS itself.
FSCTL can be sent by means of the DeviceIoControl() system API function.
For details on defining an I/O Control Code, see "Defining I/O Control Codes" topic in MSDN.
When defining a control code, use the following macro:
#define CTL_CODE( DeviceType, Function, Method, Access ) \
( ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) )
Parameters of CTL_CODE:
DeviceType - must always be FILE_DEVICE_FILE_SYSTEM (9)
Function - should be from 2400 to 4096, because they are reserved by CBFS for application use.
TransferType - For small data (1-4096 bytes) it is better to use METHOD_BUFFERED. For big chunks use METHOD_NEITHER or others.
If the output buffer is too small to receive any data, the call fails. In this situation ECBFSConnectError(ERROR_INSUFFICIENT_BUFFER) must be thrown and BytesReturned must be set to zero.
If the output buffer is too small to hold all of the data but can hold some entries, then it's allowed to return as much data as can fit into OutputBuffer.
In this case ECBFSConnectError(ERROR_MORE_DATA) exception must be thrown, and BytesReturned parameter must be set to the amount of data actually returned.
In the case the Code parameter contains operation not supported by your callback /event handler, the code should throw ECBFSConnectError(ERROR_INVALID_FUNCTION).
In .NET you should not try to replace the OutputBuffer. Instead you need to copy the data to the provided buffer. You can use Array.Copy method for this.
Read more about contexts.
See Error handling topic for detailed information about how to report errors, which occur in the event handlers, back to CBFS Connect.
// Check whether it is your CBFS storage:
#define FSCTL_IS_MINE_STORAGE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 2400, METHOD_BUFFERED, FILE_ANY_ACCESS)
if (Code != FSCTL_IS_MINE_STORAGE)
// Get file "secret" information:
#define FSCTL_GET_FILE_SECRET_INFO CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 2400, METHOD_BUFFERED, FILE_ANY_ACCESS)
if (Code != FSCTL_GET_FILE_SECRET_INFO)
char SecretInfo = "some data";
if (OutputBufferLength < sizeof(SecretInfo))
memcpy(OutputBuffer, SecretInfo, sizeof(SecretInfo));
*BytesReturned = sizeof(SecretInfo);