Discuss this help topic in CBFS Forum

OnFsctl event/delegate/callback

Filter:

Pascal    C++ (Lib)    C++ (VCL)    C++ (.NET)    C#    VB.NET    Java 

CallbackFileSystem     See also    

Overview

This event is fired when the filesystem receives the non-standard request (filesystem control code).

Declaration

[Pascal]
    property OnFsctl : TCbFsFsctlEvent;
    TCbFsFsctlEvent = procedure( Sender : TObject; FileInfo: TCbFsFileInfo; Code: LongWord; var InputBuffer; InputBufferLength: LongWord; var OutputBuffer; OutputBufferLength: LongWord; var BytesReturned: LongWord ) of object;

[C++ (Lib)]
    void (__stdcall *CbFsFsctlEvent)(void* Sender, CbFsFileInfo* FileInfo, DWORD Code, PVOID InputBuffer, DWORD InputBufferLength, PVOID OutputBuffer, DWORD OutputBufferLength, PDWORD BytesReturned );

[C++ (VCL)]
    typedef void (__closure *TCbFsFsctlEvent)( System::TObject* Sender, TCbFsFileInfo* FileInfo, unsigned Code, void *InputBuffer, unsigned long InputBufferLength, void *OutputBuffer, unsigned long OutputBufferLength, unsigned long &BytesReturned );

[C++ (.NET)]
    public __delegate void CbFsFsctlEvent( CallbackFileSystem^ Sender, CbFsFileInfo^ FileInfo, UInt32 Code, IntPtr InputBuffer, UInt32 InputBufferLength, IntPtr OutputBuffer, UInt32 OutputBufferLength, UInt32% BytesReturned );

[C#]
    public void CbFsFsctlEvent( CallbackFileSystem Sender, CbFsFileInfo FileInfo, UInt32 Code, IntPtr InputBuffer, UInt32 InputBufferLength, IntPtr OutputBuffer, UInt32 OutputBufferLength, UInt32% BytesReturned );

[VB.NET]
    Sub CbFsFsctlEvent( ByVal Sender As CallbackFileSystem, ByVal FileInfo As CbFsFileInfo, ByVal Code As UInt32; ByVal InputBuffer as IntPtr; ByVal InputBufferLength as UInt32; ByVal OutputBuffer As IntPtr; ByVal OutputBufferLength as UInt32; ByRef BytesReturned as UInt32 )

[Java]
    void ICbFsFileEvents.onFsCtl( CallbackFileSystem sender, CbFsFileInfo fileInfo, int Code, byteArrayRef inputBuffer, int inputBufferLength, byteArrayRef outputBuffer, int outputBufferLength, intRef bytesReturned );

Parameters

  • Sender - reference to the class that called the delegate/event handler
  • FileInfo - contains information about the file. Can be nil / NULL / null / Nothing in the case the event is sent to the volume (not to a file or directory).
  • Code - The control code for the operation. This value identifies the specific operation to be performed.
  • InputBuffer - A pointer to the input buffer that contains the data required to perform the operation. The format of this data depends on the value of the Code parameter. This parameter can be NULL or empty if Code specifies an operation that does not require input data.
  • InputBufferLength - The size of the input buffer, in bytes.
  • OutputBuffer - A pointer to the output buffer that is to receive the data returned by the operation. The format of this data depends on the value of the Code parameter. This parameter can be NULL if Code specifies an operation that does not return data.
  • OutputBufferLength - The size of the output buffer, in bytes.
  • BytesReturned - The size of the data stored in the output buffer, in bytes.

Description

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 ECBFSError(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 ECBFSError(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 ECBFSError(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.

Error handling

See Error handling topic for detailed information about how to report errors, which occur in the event handlers, back to Callback File System.

See also

OnCreateFile     OnOpenFile     OnWriteFile    

Examples

// Check whether it is your CBFS storage:

#define FSCTL_IS_MINE_STORAGE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 2400, METHOD_BUFFERED, FILE_ANY_ACCESS)

void CbFsFsctl(
    CallbackFileSystem* Sender,
    CbFsFileInfo* FileInfo,
    DWORD Code,
    PVOID InputBuffer,
    DWORD InputBufferLength,
    PVOID OutputBuffer,
    DWORD OutputBufferLength,
    PDWORD BytesReturned
    )
{
    if (Code != FSCTL_IS_MINE_STORAGE)
        throw ECBFSError(ERROR_INVALID_FUNCTION);
}

// Get file "secret" information:

#define FSCTL_GET_FILE_SECRET_INFO CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 2400, METHOD_BUFFERED, FILE_ANY_ACCESS)

void CbFsFsctl(
    CallbackFileSystem* Sender,
    CbFsFileInfo* FileInfo,
    DWORD Code,
    PVOID InputBuffer,
    DWORD InputBufferLength,
    PVOID OutputBuffer,
    DWORD OutputBufferLength,
    PDWORD BytesReturned
    )
{
    if (Code != FSCTL_GET_FILE_SECRET_INFO)
        throw ECBFSError(ERROR_INVALID_FUNCTION);

    char SecretInfo[] = "some data";
    if (OutputBufferLength < sizeof(SecretInfo))
        throw ECBFSError(ERROR_INSUFFICIENT_BUFFER);

    memcpy(OutputBuffer, SecretInfo, sizeof(SecretInfo));
    *BytesReturned = sizeof(SecretInfo);
}

Discuss this help topic in CBFS Forum