winfsp/inc/winfsp/fsctl.h
Bill Zissimopoulos 1239c610a5 sys: IRP_MJ_READ: remove FspFileNodeTrySetFileInfo at completion
sys: IRP_MJ_READ: remove PagingIo early exit optimization
sys: IRP_MJ_WRITE: remove PagingIo early exit optimization
2016-04-13 20:33:10 -07:00

413 lines
14 KiB
C

/**
* @file winfsp/fsctl.h
*
* @copyright 2015-2016 Bill Zissimopoulos
*/
#ifndef WINFSP_FSCTL_H_INCLUDED
#define WINFSP_FSCTL_H_INCLUDED
#include <devioctl.h>
#ifdef __cplusplus
extern "C" {
#endif
#define FSP_FSCTL_DISK_DEVICE_NAME "WinFsp.Disk"
#define FSP_FSCTL_NET_DEVICE_NAME "WinFsp.Net"
#define FSP_FSCTL_VOLUME_PARAMS_PREFIX "\\VolumeParams="
// {6F9D25FA-6DEE-4A9D-80F5-E98E14F35E54}
extern const __declspec(selectany) GUID FspFsctlDeviceClassGuid =
{ 0x6f9d25fa, 0x6dee, 0x4a9d, { 0x80, 0xf5, 0xe9, 0x8e, 0x14, 0xf3, 0x5e, 0x54 } };
// {B48171C3-DD50-4852-83A3-344C50D93B17}
extern const __declspec(selectany) GUID FspFsvrtDeviceClassGuid =
{ 0xb48171c3, 0xdd50, 0x4852, { 0x83, 0xa3, 0x34, 0x4c, 0x50, 0xd9, 0x3b, 0x17 } };
/* alignment macros */
#define FSP_FSCTL_ALIGN_UP(x, s) (((x) + ((s) - 1L)) & ~((s) - 1L))
#define FSP_FSCTL_DEFAULT_ALIGNMENT 8
#define FSP_FSCTL_DEFAULT_ALIGN_UP(x) FSP_FSCTL_ALIGN_UP(x, FSP_FSCTL_DEFAULT_ALIGNMENT)
#define FSP_FSCTL_DECLSPEC_ALIGN __declspec(align(FSP_FSCTL_DEFAULT_ALIGNMENT))
/* fsctl device codes */
#define FSP_FSCTL_VOLUME_NAME \
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'N', METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSP_FSCTL_TRANSACT \
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'T', METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSP_FSCTL_TRANSACT_BATCH \
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 't', METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
#define FSP_FSCTL_STOP \
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'S', METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSP_FSCTL_VOLUME_NAME_SIZEMAX 128
#define FSP_FSCTL_TRANSACT_REQ_SIZEMAX (4096 - 64) /* 64: size for internal request header */
#define FSP_FSCTL_TRANSACT_RSP_SIZEMAX (4096 - 64) /* symmetry! */
#define FSP_FSCTL_TRANSACT_BATCH_BUFFER_SIZEMIN 16384
#define FSP_FSCTL_TRANSACT_BUFFER_SIZEMIN FSP_FSCTL_TRANSACT_REQ_SIZEMAX
/* marshalling */
#pragma warning(push)
#pragma warning(disable:4200) /* zero-sized array in struct/union */
enum
{
FspFsctlTransactReservedKind = 0,
FspFsctlTransactCreateKind,
FspFsctlTransactOverwriteKind,
FspFsctlTransactCleanupKind,
FspFsctlTransactCloseKind,
FspFsctlTransactReadKind,
FspFsctlTransactWriteKind,
FspFsctlTransactQueryInformationKind,
FspFsctlTransactSetInformationKind,
FspFsctlTransactQueryEaKind,
FspFsctlTransactSetEaKind,
FspFsctlTransactFlushBuffersKind,
FspFsctlTransactQueryVolumeInformationKind,
FspFsctlTransactSetVolumeInformationKind,
FspFsctlTransactQueryDirectoryKind,
FspFsctlTransactFileSystemControlKind,
FspFsctlTransactDeviceControlKind,
FspFsctlTransactShutdownKind,
FspFsctlTransactLockControlKind,
FspFsctlTransactQuerySecurityKind,
FspFsctlTransactSetSecurityKind,
FspFsctlTransactKindCount,
};
enum
{
FspFsctlTransactTimeoutMinimum = 1000,
FspFsctlTransactTimeoutMaximum = 10000,
FspFsctlTransactTimeoutDefault = 1000,
FspFsctlIrpTimeoutMinimum = 60000,
FspFsctlIrpTimeoutMaximum = 600000,
FspFsctlIrpTimeoutDefault = 300000,
FspFsctlIrpTimeoutDebug = 142, /* special value for IRP timeout testing */
FspFsctlIrpCapacityMinimum = 100,
FspFsctlIrpCapacityMaximum = 1000,
FspFsctlIrpCapacityDefault = 1000,
};
typedef struct
{
UINT16 Version; /* set to 0 */
/* volume information */
UINT16 SectorSize;
UINT16 SectorsPerAllocationUnit;
UINT16 MaxComponentLength; /* maximum file name component length (bytes) */
UINT64 VolumeCreationTime;
UINT32 VolumeSerialNumber;
/* I/O timeouts, capacity, etc. */
UINT32 TransactTimeout; /* FSP_FSCTL_TRANSACT timeout (millis; 1 sec - 10 sec) */
UINT32 IrpTimeout; /* pending IRP timeout (millis; 1 min - 10 min) */
UINT32 IrpCapacity; /* maximum number of pending IRP's (100 - 1000)*/
UINT32 FileInfoTimeout; /* FileInfo/Security/VolumeInfo timeout (millis) */
/* FILE_FS_ATTRIBUTE_INFORMATION::FileSystemAttributes */
UINT32 CaseSensitiveSearch:1; /* file system supports case-sensitive file names */
UINT32 CasePreservedNames:1; /* file system preserves the case of file names */
UINT32 UnicodeOnDisk:1; /* file system supports Unicode in file names */
UINT32 PersistentAcls:1; /* file system preserves and enforces access control lists */
UINT32 ReparsePoints:1; /* file system supports reparse points (!!!: unimplemented) */
UINT32 NamedStreams:1; /* file system supports named streams (!!!: unimplemented) */
UINT32 HardLinks:1; /* unimplemented; set to 0 */
UINT32 ExtendedAttributes:1; /* unimplemented; set to 0 */
UINT32 ReadOnlyVolume:1;
WCHAR Prefix[64]; /* UNC prefix to recognize (\\server\path format, 0-term) */
} FSP_FSCTL_VOLUME_PARAMS;
typedef struct
{
UINT64 TotalSize;
UINT64 FreeSize;
UINT16 VolumeLabelLength;
WCHAR VolumeLabel[32];
} FSP_FSCTL_VOLUME_INFO;
typedef struct
{
UINT32 FileAttributes;
UINT32 ReparseTag;
UINT64 AllocationSize;
UINT64 FileSize;
UINT64 CreationTime;
UINT64 LastAccessTime;
UINT64 LastWriteTime;
UINT64 ChangeTime;
UINT64 IndexNumber;
} FSP_FSCTL_FILE_INFO;
typedef struct
{
UINT16 Size;
FSP_FSCTL_FILE_INFO FileInfo;
UINT64 NextOffset;
UINT8 Padding[24];
/* make struct as big as FILE_ID_BOTH_DIR_INFORMATION; allows for in-place copying */
WCHAR FileNameBuf[];
} FSP_FSCTL_DIR_INFO;
typedef struct
{
UINT16 Offset;
UINT16 Size;
} FSP_FSCTL_TRANSACT_BUF;
typedef struct
{
UINT16 Version;
UINT16 Size;
UINT32 Kind;
UINT64 Hint;
union
{
struct
{
UINT32 CreateOptions; /* Disposition: high 8 bits; Options: low 24 bits */
UINT32 FileAttributes; /* file attributes for new files */
FSP_FSCTL_TRANSACT_BUF SecurityDescriptor; /* security descriptor for new files */
UINT64 AllocationSize; /* initial allocation size */
UINT64 AccessToken; /* request access token (HANDLE) */
UINT32 DesiredAccess; /* FILE_{READ_DATA,WRITE_DATA,etc.} */
UINT32 ShareAccess; /* FILE_SHARE_{READ,WRITE,DELETE} */
FSP_FSCTL_TRANSACT_BUF Ea; /* reserved; not currently implemented */
UINT32 UserMode:1; /* request originated in user mode */
UINT32 HasTraversePrivilege:1; /* requestor has TOKEN_HAS_TRAVERSE_PRIVILEGE */
UINT32 OpenTargetDirectory:1; /* open target dir and report FILE_{EXISTS,DOES_NOT_EXIST} */
UINT32 CaseSensitive:1; /* FileName comparisons should be case-sensitive */
} Create;
struct
{
UINT64 UserContext;
UINT64 UserContext2;
UINT32 FileAttributes; /* file attributes for overwritten/superseded files */
UINT32 Supersede:1; /* 0: FILE_OVERWRITE operation, 1: FILE_SUPERSEDE operation */
} Overwrite;
struct
{
UINT64 UserContext;
UINT64 UserContext2;
UINT32 Delete:1; /* file must be deleted */
} Cleanup;
struct
{
UINT64 UserContext;
UINT64 UserContext2;
} Close;
struct
{
UINT64 UserContext;
UINT64 UserContext2;
UINT64 Address;
UINT64 Offset;
UINT32 Length;
UINT32 Key;
} Read;
struct
{
UINT64 UserContext;
UINT64 UserContext2;
UINT64 Address;
UINT64 Offset;
UINT32 Length;
UINT32 Key;
UINT32 ConstrainedIo:1;
} Write;
struct
{
UINT64 UserContext;
UINT64 UserContext2;
} QueryInformation;
struct
{
UINT64 UserContext;
UINT64 UserContext2;
UINT32 FileInformationClass;
union
{
struct
{
UINT64 AllocationSize;
} Allocation;
struct
{
UINT32 FileAttributes;
UINT64 CreationTime;
UINT64 LastAccessTime;
UINT64 LastWriteTime;
} Basic;
struct
{
UINT32 Delete:1;
} Disposition;
struct
{
UINT64 FileSize;
} EndOfFile;
struct
{
FSP_FSCTL_TRANSACT_BUF NewFileName;
UINT32 ReplaceIfExists:1;
} Rename;
} Info;
} SetInformation;
struct
{
UINT64 UserContext;
UINT64 UserContext2;
} FlushBuffers;
struct
{
UINT32 FsInformationClass;
union
{
struct
{
FSP_FSCTL_TRANSACT_BUF VolumeLabel;
} Label;
} Info;
} SetVolumeInformation;
struct
{
UINT64 UserContext;
UINT64 UserContext2;
UINT64 Address;
UINT64 Offset;
UINT32 Length;
} QueryDirectory;
struct
{
UINT64 UserContext;
UINT64 UserContext2;
} QuerySecurity;
struct
{
UINT64 UserContext;
UINT64 UserContext2;
UINT32 SecurityInformation;
UINT64 AccessToken; /* request access token (HANDLE) */
FSP_FSCTL_TRANSACT_BUF SecurityDescriptor;
} SetSecurity;
} Req;
FSP_FSCTL_TRANSACT_BUF FileName; /* {Create,Cleanup,SetInformation/{...},QueryDirectory} */
FSP_FSCTL_DECLSPEC_ALIGN UINT8 Buffer[];
} FSP_FSCTL_TRANSACT_REQ;
typedef struct
{
UINT16 Version;
UINT16 Size;
UINT32 Kind;
UINT64 Hint;
struct
{
UINT64 Information;
UINT32 Status;
} IoStatus;
union
{
union
{
/* IoStatus.Status == STATUS_SUCCESS */
struct
{
UINT64 UserContext; /* user context associated with file node */
UINT64 UserContext2; /* user context associated with file descriptor (handle) */
UINT32 GrantedAccess; /* FILE_{READ_DATA,WRITE_DATA,etc.} */
FSP_FSCTL_FILE_INFO FileInfo;
} Opened;
/* IoStatus.Status == STATUS_REPARSE */
struct
{
FSP_FSCTL_TRANSACT_BUF FileName; /* file name to use for STATUS_REPARSE */
} Reparse;
} Create;
struct
{
FSP_FSCTL_FILE_INFO FileInfo;
} Overwrite;
struct
{
FSP_FSCTL_FILE_INFO FileInfo;
} Write;
struct
{
FSP_FSCTL_FILE_INFO FileInfo;
} QueryInformation;
struct
{
FSP_FSCTL_FILE_INFO FileInfo; /* valid: File{Allocation,Basic,EndOfFile}Information */
} SetInformation;
struct
{
FSP_FSCTL_VOLUME_INFO VolumeInfo;
} QueryVolumeInformation;
struct
{
FSP_FSCTL_VOLUME_INFO VolumeInfo;
} SetVolumeInformation;
struct
{
FSP_FSCTL_TRANSACT_BUF SecurityDescriptor;
} QuerySecurity;
struct
{
FSP_FSCTL_TRANSACT_BUF SecurityDescriptor; /* Size==0 means no security descriptor returned */
} SetSecurity;
} Rsp;
FSP_FSCTL_DECLSPEC_ALIGN UINT8 Buffer[];
} FSP_FSCTL_TRANSACT_RSP;
#pragma warning(pop)
static inline BOOLEAN FspFsctlTransactCanProduceRequest(
FSP_FSCTL_TRANSACT_REQ *Request, PVOID RequestBufEnd)
{
return (PUINT8)Request + FSP_FSCTL_TRANSACT_REQ_SIZEMAX <= (PUINT8)RequestBufEnd;
}
static inline FSP_FSCTL_TRANSACT_REQ *FspFsctlTransactProduceRequest(
FSP_FSCTL_TRANSACT_REQ *Request, SIZE_T RequestSize)
{
PVOID NextRequest = (PUINT8)Request + FSP_FSCTL_DEFAULT_ALIGN_UP(RequestSize);
return (FSP_FSCTL_TRANSACT_REQ *)NextRequest;
}
static inline FSP_FSCTL_TRANSACT_REQ *FspFsctlTransactConsumeRequest(
FSP_FSCTL_TRANSACT_REQ *Request, PVOID RequestBufEnd)
{
if ((PUINT8)Request + sizeof(Request->Size) > (PUINT8)RequestBufEnd ||
sizeof(FSP_FSCTL_TRANSACT_REQ) > Request->Size)
return 0;
PVOID NextRequest = (PUINT8)Request + FSP_FSCTL_DEFAULT_ALIGN_UP(Request->Size);
return NextRequest <= RequestBufEnd ? (FSP_FSCTL_TRANSACT_REQ *)NextRequest : 0;
}
static inline BOOLEAN FspFsctlTransactCanProduceResponse(
FSP_FSCTL_TRANSACT_RSP *Response, PVOID ResponseBufEnd)
{
return (PUINT8)Response + FSP_FSCTL_TRANSACT_RSP_SIZEMAX <= (PUINT8)ResponseBufEnd;
}
static inline FSP_FSCTL_TRANSACT_RSP *FspFsctlTransactProduceResponse(
FSP_FSCTL_TRANSACT_RSP *Response, SIZE_T ResponseSize)
{
PVOID NextResponse = (PUINT8)Response + FSP_FSCTL_DEFAULT_ALIGN_UP(ResponseSize);
return (FSP_FSCTL_TRANSACT_RSP *)NextResponse;
}
static inline FSP_FSCTL_TRANSACT_RSP *FspFsctlTransactConsumeResponse(
FSP_FSCTL_TRANSACT_RSP *Response, PVOID ResponseBufEnd)
{
if ((PUINT8)Response + sizeof(Response->Size) > (PUINT8)ResponseBufEnd ||
sizeof(FSP_FSCTL_TRANSACT_RSP) > Response->Size)
return 0;
PVOID NextResponse = (PUINT8)Response + FSP_FSCTL_DEFAULT_ALIGN_UP(Response->Size);
return NextResponse <= ResponseBufEnd ? (FSP_FSCTL_TRANSACT_RSP *)NextResponse : 0;
}
#if !defined(WINFSP_SYS_INTERNAL)
FSP_API NTSTATUS FspFsctlCreateVolume(PWSTR DevicePath,
const FSP_FSCTL_VOLUME_PARAMS *VolumeParams,
PWCHAR VolumeNameBuf, SIZE_T VolumeNameSize,
PHANDLE PVolumeHandle);
FSP_API NTSTATUS FspFsctlTransact(HANDLE VolumeHandle,
PVOID ResponseBuf, SIZE_T ResponseBufSize,
PVOID RequestBuf, SIZE_T *PRequestBufSize,
BOOLEAN Batch);
FSP_API NTSTATUS FspFsctlStop(HANDLE VolumeHandle);
#endif
#ifdef __cplusplus
}
#endif
#endif