Fires when the virtual filesystem receives a non-standard request (filesystem control code).
class CBFSFsctlEventParams(object): @property def file_name() -> str: ... @property def code() -> int: ... @property def input_buffer() -> c_void_p: ... @property def input_buffer_length() -> int: ... @property def output_buffer() -> c_void_p: ... @property def output_buffer_length() -> int: ... @property def bytes_returned() -> int: ... @bytes_returned.setter def bytes_returned(value) -> None: ... @property def file_context() -> int: ... @file_context.setter def file_context(value) -> None: ... @property def result_code() -> int: ... @result_code.setter def result_code(value) -> None: ... # In class CBFS: @property def on_fsctl() -> Callable[[CBFSFsctlEventParams], None]: ... @on_fsctl.setter def on_fsctl(event_hook: Callable[[CBFSFsctlEventParams], None]) -> None: ...
An FSCTL is a system call for filesystem-specific I/O operations, as well as other operations that cannot be expressed through regular filesystem calls. Such calls carry a control code, and the effects of the call depend entirely on how a filesystem handles that control code. A control code is composed of, among other things, a function code and flags that describe how data is passed.
CBFS Connect reserves function codes 2400-4096 for applications' use, and normally only fires this event for control codes containing a function code from that range. However, if the handle_all_fsctls property is enabled, the class will fire this event for all FSCTLs other than those processed by CBFS Connect itself.
This event is optional. Applications that choose to implement it are free to do so in any manner they desire based on the control code received.
An application can send a custom FSCTL by defining a control code with the macro shown below, and then using that control code to call the Windows API's DeviceIoControl function.
#define CTL_CODE( DeviceType, Function, Method, Access ) \ ( ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) )
- DeviceType: Must always be FILE_DEVICE_FILE_SYSTEM (9).
- Function: Must be an integer in the range 2400-4096.
- Method ("TransferType"): Specifies how data is passed between the caller and the driver. Possible values are:
- METHOD_BUFFERED (0)
- METHOD_IN_DIRECT (1)
- METHOD_OUT_DIRECT (2)
- METHOD_NEITHER (3)
- Access ("RequiredAccess"): Indicates the type(s) of access the caller must request when opening a handle to the target filesystem object
(i.e., the handle passed for the hDevice parameter of the DeviceIoControl function).
The system's I/O manager will block the request if the caller didn't open said handle with the required access rights. Possible values are:
- FILE_ANY_ACCESS (0) (i.e., the caller can send the FSCTL regardless of access rights)
- FILE_READ_ACCESS (1)
- FILE_WRITE_ACCESS (2)
Please refer to Microsoft's Defining I/O Control Codes article for more information.
The FileName parameter identifies the file or directory targeted by the request. It may be empty if the request is targeting the virtual drive itself.
The Code parameter reflects the control code received. If the specified control code is unrecognized or unsupported (either in general, or for the filesystem object specified by FileName), return the ERROR_INVALID_FUNCTION error code via ResultCode.
The InputBuffer parameter points to the memory buffer containing the data required to perform the operation. The format of this data depends on the specified Code; it may be empty. The InputBufferLength parameter specifies the length, in bytes, of InputBuffer.
The OutputBuffer parameter points to the memory buffer that receives the data returned by the operation. The format of this data depends on the specified Code; it may be empty. The OutputBufferLength parameter specifies the capacity, in bytes, of OutputBuffer; applications should set the BytesReturned parameter to the number of bytes written to OutputBuffer.
If the application needs to return more than OutputBufferLength bytes of data, it should do one of the following things:
- If OutputBuffer is too small to hold all of the data, but can hold some entries, then the application should write as much data to it as possible, set BytesReturned appropriately, and return the ERROR_MORE_DATA error code via ResultCode.
- If OutputBuffer is too small to hold any data, then the application should set BytesReturned to 0, and return the ERROR_INSUFFICIENT_BUFFER error code via ResultCode.
Please refer to the Buffer Parameters topic for more information on how to work with memory buffer event parameters.
The FileContext parameter is a placeholder for application-defined data associated with the file. Please refer to the Contexts topic for more information.
The ResultCode parameter will always be 0 when the event is fired. If the event cannot be handled in a "successful" manner for some reason (e.g., a resource isn't available, security checks failed, etc.), set it to a non-zero value to report an appropriate error. Please refer to the Error Reporting and Handling topic for more information.