upgraded winfsp to v2.1
Some checks failed
BlockStorage/repertory/pipeline/head There was a failure building this commit

This commit is contained in:
2025-07-21 10:59:07 -05:00
parent 1ea2d1496d
commit 39fcce0e88
57 changed files with 8650 additions and 8257 deletions

View File

@@ -0,0 +1,271 @@
/**
* @file fuse/fuse.h
* WinFsp FUSE compatible API.
*
* This file is derived from libfuse/include/fuse.h:
* FUSE: Filesystem in Userspace
* Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
*
* @copyright 2015-2025 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
*
* You can redistribute it and/or modify it under the terms of the GNU
* General Public License version 3 as published by the Free Software
* Foundation.
*
* Licensees holding a valid commercial license may use this software
* in accordance with the commercial license agreement provided in
* conjunction with the software. The terms and conditions of any such
* commercial license agreement shall govern, supersede, and render
* ineffective any application of the GPLv3 license to this software,
* notwithstanding of any reference thereto in the software or
* associated repository.
*/
#ifndef FUSE_H_
#define FUSE_H_
#include "fuse_common.h"
#ifdef __cplusplus
extern "C" {
#endif
struct fuse;
typedef int (*fuse_fill_dir_t)(void *buf, const char *name,
const struct fuse_stat *stbuf, fuse_off_t off);
typedef struct fuse_dirhandle *fuse_dirh_t;
typedef int (*fuse_dirfil_t)(fuse_dirh_t h, const char *name,
int type, fuse_ino_t ino);
struct fuse_operations
{
/* S - supported by WinFsp */
/* S */ int (*getattr)(const char *path, struct fuse_stat *stbuf);
/* S */ int (*getdir)(const char *path, fuse_dirh_t h, fuse_dirfil_t filler);
/* S */ int (*readlink)(const char *path, char *buf, size_t size);
/* S */ int (*mknod)(const char *path, fuse_mode_t mode, fuse_dev_t dev);
/* S */ int (*mkdir)(const char *path, fuse_mode_t mode);
/* S */ int (*unlink)(const char *path);
/* S */ int (*rmdir)(const char *path);
/* S */ int (*symlink)(const char *dstpath, const char *srcpath);
/* S */ int (*rename)(const char *oldpath, const char *newpath);
/* _ */ int (*link)(const char *srcpath, const char *dstpath);
/* S */ int (*chmod)(const char *path, fuse_mode_t mode);
/* S */ int (*chown)(const char *path, fuse_uid_t uid, fuse_gid_t gid);
/* S */ int (*truncate)(const char *path, fuse_off_t size);
/* S */ int (*utime)(const char *path, struct fuse_utimbuf *timbuf);
/* S */ int (*open)(const char *path, struct fuse_file_info *fi);
/* S */ int (*read)(const char *path, char *buf, size_t size, fuse_off_t off,
struct fuse_file_info *fi);
/* S */ int (*write)(const char *path, const char *buf, size_t size, fuse_off_t off,
struct fuse_file_info *fi);
/* S */ int (*statfs)(const char *path, struct fuse_statvfs *stbuf);
/* S */ int (*flush)(const char *path, struct fuse_file_info *fi);
/* S */ int (*release)(const char *path, struct fuse_file_info *fi);
/* S */ int (*fsync)(const char *path, int datasync, struct fuse_file_info *fi);
/* S */ int (*setxattr)(const char *path, const char *name, const char *value, size_t size,
int flags);
/* S */ int (*getxattr)(const char *path, const char *name, char *value, size_t size);
/* S */ int (*listxattr)(const char *path, char *namebuf, size_t size);
/* S */ int (*removexattr)(const char *path, const char *name);
/* S */ int (*opendir)(const char *path, struct fuse_file_info *fi);
/* S */ int (*readdir)(const char *path, void *buf, fuse_fill_dir_t filler, fuse_off_t off,
struct fuse_file_info *fi);
/* S */ int (*releasedir)(const char *path, struct fuse_file_info *fi);
/* S */ int (*fsyncdir)(const char *path, int datasync, struct fuse_file_info *fi);
/* S */ void *(*init)(struct fuse_conn_info *conn);
/* S */ void (*destroy)(void *data);
/* S */ int (*access)(const char *path, int mask);
/* S */ int (*create)(const char *path, fuse_mode_t mode, struct fuse_file_info *fi);
/* S */ int (*ftruncate)(const char *path, fuse_off_t off, struct fuse_file_info *fi);
/* S */ int (*fgetattr)(const char *path, struct fuse_stat *stbuf, struct fuse_file_info *fi);
/* _ */ int (*lock)(const char *path,
struct fuse_file_info *fi, int cmd, struct fuse_flock *lock);
/* S */ int (*utimens)(const char *path, const struct fuse_timespec tv[2]);
/* _ */ int (*bmap)(const char *path, size_t blocksize, uint64_t *idx);
/* _ */ unsigned int flag_nullpath_ok:1;
/* _ */ unsigned int flag_nopath:1;
/* _ */ unsigned int flag_utime_omit_ok:1;
/* _ */ unsigned int flag_reserved:29;
/* S */ int (*ioctl)(const char *path, int cmd, void *arg, struct fuse_file_info *fi,
unsigned int flags, void *data);
/* _ */ int (*poll)(const char *path, struct fuse_file_info *fi,
struct fuse_pollhandle *ph, unsigned *reventsp);
/* FUSE 2.9 */
/* _ */ int (*write_buf)(const char *path,
struct fuse_bufvec *buf, fuse_off_t off, struct fuse_file_info *fi);
/* _ */ int (*read_buf)(const char *path,
struct fuse_bufvec **bufp, size_t size, fuse_off_t off, struct fuse_file_info *fi);
/* _ */ int (*flock)(const char *path, struct fuse_file_info *, int op);
/* _ */ int (*fallocate)(const char *path, int mode, fuse_off_t off, fuse_off_t len,
struct fuse_file_info *fi);
/* WinFsp */
/* S */ int (*getpath)(const char *path, char *buf, size_t size,
struct fuse_file_info *fi);
/* OSXFUSE */
/* _ */ int (*reserved01)();
/* _ */ int (*reserved02)();
/* _ */ int (*statfs_x)(const char *path, struct fuse_statfs *stbuf);
/* _ */ int (*setvolname)(const char *volname);
/* _ */ int (*exchange)(const char *oldpath, const char *newpath, unsigned long flags);
/* _ */ int (*getxtimes)(const char *path,
struct fuse_timespec *bkuptime, struct fuse_timespec *crtime);
/* _ */ int (*setbkuptime)(const char *path, const struct fuse_timespec *tv);
/* S */ int (*setchgtime)(const char *path, const struct fuse_timespec *tv);
/* S */ int (*setcrtime)(const char *path, const struct fuse_timespec *tv);
/* S */ int (*chflags)(const char *path, uint32_t flags);
/* _ */ int (*setattr_x)(const char *path, struct fuse_setattr_x *attr);
/* _ */ int (*fsetattr_x)(const char *path, struct fuse_setattr_x *attr,
struct fuse_file_info *fi);
};
struct fuse_context
{
struct fuse *fuse;
fuse_uid_t uid;
fuse_gid_t gid;
fuse_pid_t pid;
void *private_data;
fuse_mode_t umask;
};
#define fuse_main(argc, argv, ops, data)\
fuse_main_real(argc, argv, ops, sizeof *(ops), data)
FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse_main_real)(struct fsp_fuse_env *env,
int argc, char *argv[],
const struct fuse_operations *ops, size_t opsize, void *data);
FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse_is_lib_option)(struct fsp_fuse_env *env,
const char *opt);
FSP_FUSE_API struct fuse *FSP_FUSE_API_NAME(fsp_fuse_new)(struct fsp_fuse_env *env,
struct fuse_chan *ch, struct fuse_args *args,
const struct fuse_operations *ops, size_t opsize, void *data);
FSP_FUSE_API void FSP_FUSE_API_NAME(fsp_fuse_destroy)(struct fsp_fuse_env *env,
struct fuse *f);
FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse_loop)(struct fsp_fuse_env *env,
struct fuse *f);
FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse_loop_mt)(struct fsp_fuse_env *env,
struct fuse *f);
FSP_FUSE_API void FSP_FUSE_API_NAME(fsp_fuse_exit)(struct fsp_fuse_env *env,
struct fuse *f);
FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse_exited)(struct fsp_fuse_env *env,
struct fuse *f);
FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse_notify)(struct fsp_fuse_env *env,
struct fuse *f, const char *path, uint32_t action);
FSP_FUSE_API struct fuse_context *FSP_FUSE_API_NAME(fsp_fuse_get_context)(struct fsp_fuse_env *env);
FSP_FUSE_SYM(
int fuse_main_real(int argc, char *argv[],
const struct fuse_operations *ops, size_t opsize, void *data),
{
return FSP_FUSE_API_CALL(fsp_fuse_main_real)
(fsp_fuse_env(), argc, argv, ops, opsize, data);
})
FSP_FUSE_SYM(
int fuse_is_lib_option(const char *opt),
{
return FSP_FUSE_API_CALL(fsp_fuse_is_lib_option)
(fsp_fuse_env(), opt);
})
FSP_FUSE_SYM(
struct fuse *fuse_new(struct fuse_chan *ch, struct fuse_args *args,
const struct fuse_operations *ops, size_t opsize, void *data),
{
return FSP_FUSE_API_CALL(fsp_fuse_new)
(fsp_fuse_env(), ch, args, ops, opsize, data);
})
FSP_FUSE_SYM(
void fuse_destroy(struct fuse *f),
{
FSP_FUSE_API_CALL(fsp_fuse_destroy)
(fsp_fuse_env(), f);
})
FSP_FUSE_SYM(
int fuse_loop(struct fuse *f),
{
return FSP_FUSE_API_CALL(fsp_fuse_loop)
(fsp_fuse_env(), f);
})
FSP_FUSE_SYM(
int fuse_loop_mt(struct fuse *f),
{
return FSP_FUSE_API_CALL(fsp_fuse_loop_mt)
(fsp_fuse_env(), f);
})
FSP_FUSE_SYM(
void fuse_exit(struct fuse *f),
{
FSP_FUSE_API_CALL(fsp_fuse_exit)
(fsp_fuse_env(), f);
})
FSP_FUSE_SYM(
int fuse_exited(struct fuse *f),
{
return FSP_FUSE_API_CALL(fsp_fuse_exited)
(fsp_fuse_env(), f);
})
FSP_FUSE_SYM(
int fuse_notify(struct fuse *f, const char *path, uint32_t action),
{
return FSP_FUSE_API_CALL(fsp_fuse_notify)
(fsp_fuse_env(), f, path, action);
})
FSP_FUSE_SYM(
struct fuse_context *fuse_get_context(void),
{
return FSP_FUSE_API_CALL(fsp_fuse_get_context)
(fsp_fuse_env());
})
FSP_FUSE_SYM(
int fuse_getgroups(int size, fuse_gid_t list[]),
{
(void)size;
(void)list;
return -ENOSYS;
})
FSP_FUSE_SYM(
int fuse_interrupted(void),
{
return 0;
})
FSP_FUSE_SYM(
int fuse_invalidate(struct fuse *f, const char *path),
{
return FSP_FUSE_API_CALL(fsp_fuse_notify)
(fsp_fuse_env(), f, path, 0);
})
FSP_FUSE_SYM(
int fuse_notify_poll(struct fuse_pollhandle *ph),
{
(void)ph;
return 0;
})
FSP_FUSE_SYM(
struct fuse_session *fuse_get_session(struct fuse *f),
{
return (struct fuse_session *)f;
})
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,202 @@
/**
* @file fuse/fuse_common.h
* WinFsp FUSE compatible API.
*
* This file is derived from libfuse/include/fuse_common.h:
* FUSE: Filesystem in Userspace
* Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
*
* @copyright 2015-2025 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
*
* You can redistribute it and/or modify it under the terms of the GNU
* General Public License version 3 as published by the Free Software
* Foundation.
*
* Licensees holding a valid commercial license may use this software
* in accordance with the commercial license agreement provided in
* conjunction with the software. The terms and conditions of any such
* commercial license agreement shall govern, supersede, and render
* ineffective any application of the GPLv3 license to this software,
* notwithstanding of any reference thereto in the software or
* associated repository.
*/
#ifndef FUSE_COMMON_H_
#define FUSE_COMMON_H_
#include "winfsp_fuse.h"
#include "fuse_opt.h"
#ifdef __cplusplus
extern "C" {
#endif
#define FUSE_MAJOR_VERSION 2
#define FUSE_MINOR_VERSION 8
#define FUSE_MAKE_VERSION(maj, min) ((maj) * 10 + (min))
#define FUSE_VERSION FUSE_MAKE_VERSION(FUSE_MAJOR_VERSION, FUSE_MINOR_VERSION)
#define FUSE_CAP_ASYNC_READ (1 << 0)
#define FUSE_CAP_POSIX_LOCKS (1 << 1)
#define FUSE_CAP_ATOMIC_O_TRUNC (1 << 3)
#define FUSE_CAP_EXPORT_SUPPORT (1 << 4)
#define FUSE_CAP_BIG_WRITES (1 << 5)
#define FUSE_CAP_DONT_MASK (1 << 6)
#define FUSE_CAP_ALLOCATE (1 << 27) /* reserved (OSXFUSE) */
#define FUSE_CAP_EXCHANGE_DATA (1 << 28) /* reserved (OSXFUSE) */
#define FUSE_CAP_CASE_INSENSITIVE (1 << 29) /* file system is case insensitive */
#define FUSE_CAP_VOL_RENAME (1 << 30) /* reserved (OSXFUSE) */
#define FUSE_CAP_XTIMES (1 << 31) /* reserved (OSXFUSE) */
#define FSP_FUSE_CAP_READDIR_PLUS (1 << 21) /* file system supports enhanced readdir */
#define FSP_FUSE_CAP_READ_ONLY (1 << 22) /* file system is marked read-only */
#define FSP_FUSE_CAP_STAT_EX (1 << 23) /* file system supports fuse_stat_ex */
#define FSP_FUSE_CAP_DELETE_ACCESS (1 << 24) /* file system supports access with DELETE_OK */
#define FSP_FUSE_CAP_CASE_INSENSITIVE FUSE_CAP_CASE_INSENSITIVE
#define FUSE_IOCTL_COMPAT (1 << 0)
#define FUSE_IOCTL_UNRESTRICTED (1 << 1)
#define FUSE_IOCTL_RETRY (1 << 2)
#define FUSE_IOCTL_MAX_IOV 256
/* from FreeBSD */
#define FSP_FUSE_UF_HIDDEN 0x00008000
#define FSP_FUSE_UF_READONLY 0x00001000
#define FSP_FUSE_UF_SYSTEM 0x00000080
#define FSP_FUSE_UF_ARCHIVE 0x00000800
#if !defined(UF_HIDDEN)
#define UF_HIDDEN FSP_FUSE_UF_HIDDEN
#endif
#if !defined(UF_READONLY)
#define UF_READONLY FSP_FUSE_UF_READONLY
#endif
#if !defined(UF_SYSTEM)
#define UF_SYSTEM FSP_FUSE_UF_SYSTEM
#endif
#if !defined(UF_ARCHIVE)
#define UF_ARCHIVE FSP_FUSE_UF_ARCHIVE
#endif
/* delete access */
#define FSP_FUSE_DELETE_OK 0x40000000
/* notify extension */
#define FSP_FUSE_NOTIFY_MKDIR 0x0001
#define FSP_FUSE_NOTIFY_RMDIR 0x0002
#define FSP_FUSE_NOTIFY_CREATE 0x0004
#define FSP_FUSE_NOTIFY_UNLINK 0x0008
#define FSP_FUSE_NOTIFY_CHMOD 0x0010
#define FSP_FUSE_NOTIFY_CHOWN 0x0020
#define FSP_FUSE_NOTIFY_UTIME 0x0040
#define FSP_FUSE_NOTIFY_CHFLAGS 0x0080
#define FSP_FUSE_NOTIFY_TRUNCATE 0x0100
/* getpath extension */
#define FSP_FUSE_HAS_GETPATH 1
struct fuse_file_info
{
int flags;
unsigned int fh_old;
int writepage;
unsigned int direct_io:1;
unsigned int keep_cache:1;
unsigned int flush:1;
unsigned int nonseekable:1;
unsigned int padding:28;
uint64_t fh;
uint64_t lock_owner;
};
struct fuse_conn_info
{
unsigned proto_major;
unsigned proto_minor;
unsigned async_read;
unsigned max_write;
unsigned max_readahead;
unsigned capable;
unsigned want;
unsigned reserved[25];
};
struct fuse_session;
struct fuse_chan;
struct fuse_pollhandle;
struct fuse_bufvec;
struct fuse_statfs;
struct fuse_setattr_x;
FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse_version)(struct fsp_fuse_env *env);
FSP_FUSE_API struct fuse_chan *FSP_FUSE_API_NAME(fsp_fuse_mount)(struct fsp_fuse_env *env,
const char *mountpoint, struct fuse_args *args);
FSP_FUSE_API void FSP_FUSE_API_NAME(fsp_fuse_unmount)(struct fsp_fuse_env *env,
const char *mountpoint, struct fuse_chan *ch);
FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse_parse_cmdline)(struct fsp_fuse_env *env,
struct fuse_args *args,
char **mountpoint, int *multithreaded, int *foreground);
FSP_FUSE_API int32_t FSP_FUSE_API_NAME(fsp_fuse_ntstatus_from_errno)(struct fsp_fuse_env *env,
int err);
FSP_FUSE_SYM(
int fuse_version(void),
{
return FSP_FUSE_API_CALL(fsp_fuse_version)
(fsp_fuse_env());
})
FSP_FUSE_SYM(
struct fuse_chan *fuse_mount(const char *mountpoint, struct fuse_args *args),
{
return FSP_FUSE_API_CALL(fsp_fuse_mount)
(fsp_fuse_env(), mountpoint, args);
})
FSP_FUSE_SYM(
void fuse_unmount(const char *mountpoint, struct fuse_chan *ch),
{
FSP_FUSE_API_CALL(fsp_fuse_unmount)
(fsp_fuse_env(), mountpoint, ch);
})
FSP_FUSE_SYM(
int fuse_parse_cmdline(struct fuse_args *args,
char **mountpoint, int *multithreaded, int *foreground),
{
return FSP_FUSE_API_CALL(fsp_fuse_parse_cmdline)
(fsp_fuse_env(), args, mountpoint, multithreaded, foreground);
})
FSP_FUSE_SYM(
void fuse_pollhandle_destroy(struct fuse_pollhandle *ph),
{
(void)ph;
})
FSP_FUSE_SYM(
int fuse_daemonize(int foreground),
{
return fsp_fuse_daemonize(foreground);
})
FSP_FUSE_SYM(
int fuse_set_signal_handlers(struct fuse_session *se),
{
return fsp_fuse_set_signal_handlers(se);
})
FSP_FUSE_SYM(
void fuse_remove_signal_handlers(struct fuse_session *se),
{
(void)se;
fsp_fuse_set_signal_handlers(0);
})
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,133 @@
/**
* @file fuse/fuse_opt.h
* WinFsp FUSE compatible API.
*
* This file is derived from libfuse/include/fuse_opt.h:
* FUSE: Filesystem in Userspace
* Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
*
* @copyright 2015-2025 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
*
* You can redistribute it and/or modify it under the terms of the GNU
* General Public License version 3 as published by the Free Software
* Foundation.
*
* Licensees holding a valid commercial license may use this software
* in accordance with the commercial license agreement provided in
* conjunction with the software. The terms and conditions of any such
* commercial license agreement shall govern, supersede, and render
* ineffective any application of the GPLv3 license to this software,
* notwithstanding of any reference thereto in the software or
* associated repository.
*/
#ifndef FUSE_OPT_H_
#define FUSE_OPT_H_
#include "winfsp_fuse.h"
#ifdef __cplusplus
extern "C" {
#endif
#define FUSE_OPT_KEY(templ, key) { templ, -1, key }
#define FUSE_OPT_END { NULL, 0, 0 }
#define FUSE_OPT_KEY_OPT -1
#define FUSE_OPT_KEY_NONOPT -2
#define FUSE_OPT_KEY_KEEP -3
#define FUSE_OPT_KEY_DISCARD -4
#define FUSE_ARGS_INIT(argc, argv) { argc, argv, 0 }
struct fuse_opt
{
const char *templ;
unsigned int offset;
int value;
};
struct fuse_args
{
int argc;
char **argv;
int allocated;
};
typedef int (*fuse_opt_proc_t)(void *data, const char *arg, int key,
struct fuse_args *outargs);
FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse_opt_parse)(struct fsp_fuse_env *env,
struct fuse_args *args, void *data,
const struct fuse_opt opts[], fuse_opt_proc_t proc);
FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse_opt_add_arg)(struct fsp_fuse_env *env,
struct fuse_args *args, const char *arg);
FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse_opt_insert_arg)(struct fsp_fuse_env *env,
struct fuse_args *args, int pos, const char *arg);
FSP_FUSE_API void FSP_FUSE_API_NAME(fsp_fuse_opt_free_args)(struct fsp_fuse_env *env,
struct fuse_args *args);
FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse_opt_add_opt)(struct fsp_fuse_env *env,
char **opts, const char *opt);
FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse_opt_add_opt_escaped)(struct fsp_fuse_env *env,
char **opts, const char *opt);
FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse_opt_match)(struct fsp_fuse_env *env,
const struct fuse_opt opts[], const char *opt);
FSP_FUSE_SYM(
int fuse_opt_parse(struct fuse_args *args, void *data,
const struct fuse_opt opts[], fuse_opt_proc_t proc),
{
return FSP_FUSE_API_CALL(fsp_fuse_opt_parse)
(fsp_fuse_env(), args, data, opts, proc);
})
FSP_FUSE_SYM(
int fuse_opt_add_arg(struct fuse_args *args, const char *arg),
{
return FSP_FUSE_API_CALL(fsp_fuse_opt_add_arg)
(fsp_fuse_env(), args, arg);
})
FSP_FUSE_SYM(
int fuse_opt_insert_arg(struct fuse_args *args, int pos, const char *arg),
{
return FSP_FUSE_API_CALL(fsp_fuse_opt_insert_arg)
(fsp_fuse_env(), args, pos, arg);
})
FSP_FUSE_SYM(
void fuse_opt_free_args(struct fuse_args *args),
{
FSP_FUSE_API_CALL(fsp_fuse_opt_free_args)
(fsp_fuse_env(), args);
})
FSP_FUSE_SYM(
int fuse_opt_add_opt(char **opts, const char *opt),
{
return FSP_FUSE_API_CALL(fsp_fuse_opt_add_opt)
(fsp_fuse_env(), opts, opt);
})
FSP_FUSE_SYM(
int fuse_opt_add_opt_escaped(char **opts, const char *opt),
{
return FSP_FUSE_API_CALL(fsp_fuse_opt_add_opt_escaped)
(fsp_fuse_env(), opts, opt);
})
FSP_FUSE_SYM(
int fuse_opt_match(const struct fuse_opt opts[], const char *opt),
{
return FSP_FUSE_API_CALL(fsp_fuse_opt_match)
(fsp_fuse_env(), opts, opt);
})
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,435 @@
/**
* @file fuse/winfsp_fuse.h
* WinFsp FUSE compatible API.
*
* @copyright 2015-2025 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
*
* You can redistribute it and/or modify it under the terms of the GNU
* General Public License version 3 as published by the Free Software
* Foundation.
*
* Licensees holding a valid commercial license may use this software
* in accordance with the commercial license agreement provided in
* conjunction with the software. The terms and conditions of any such
* commercial license agreement shall govern, supersede, and render
* ineffective any application of the GPLv3 license to this software,
* notwithstanding of any reference thereto in the software or
* associated repository.
*/
#ifndef FUSE_WINFSP_FUSE_H_INCLUDED
#define FUSE_WINFSP_FUSE_H_INCLUDED
#include <errno.h>
#include <stdint.h>
#if !defined(WINFSP_DLL_INTERNAL)
#include <stdlib.h>
#include <string.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if !defined(FSP_FUSE_API)
#if defined(WINFSP_DLL_INTERNAL)
#define FSP_FUSE_API __declspec(dllexport)
#else
#define FSP_FUSE_API __declspec(dllimport)
#endif
#endif
#if !defined(FSP_FUSE_API_NAME)
#define FSP_FUSE_API_NAME(n) (n)
#endif
#if !defined(FSP_FUSE_API_CALL)
#define FSP_FUSE_API_CALL(n) (n)
#endif
#if !defined(FSP_FUSE_SYM)
#if !defined(CYGFUSE)
#define FSP_FUSE_SYM(proto, ...) static inline proto { __VA_ARGS__ }
#else
#define FSP_FUSE_SYM(proto, ...) proto;
#endif
#endif
#define FSP_FUSE_DEVICE_TYPE (0x8000 | 'W' | 'F' * 0x100) /* DeviceIoControl -> ioctl */
#define FSP_FUSE_CTLCODE_FROM_IOCTL(cmd)\
(FSP_FUSE_DEVICE_TYPE << 16) | (((cmd) & 0x0fff) << 2)
#define FSP_FUSE_IOCTL(cmd, isiz, osiz) \
( \
(((osiz) != 0) << 31) | \
(((isiz) != 0) << 30) | \
(((isiz) | (osiz)) << 16) | \
(cmd) \
)
/*
* FUSE uses a number of types (notably: struct stat) that are OS specific.
* Furthermore there are sometimes multiple definitions of the same type even
* within the same OS. This is certainly true on Windows, where these types
* are not even native.
*
* For this reason we will define our own fuse_* types which represent the
* types as the WinFsp DLL expects to see them. We will define these types
* to be compatible with the equivalent Cygwin types as we want WinFsp-FUSE
* to be usable from Cygwin.
*/
#define FSP_FUSE_STAT_FIELD_DEFN \
fuse_dev_t st_dev; \
fuse_ino_t st_ino; \
fuse_mode_t st_mode; \
fuse_nlink_t st_nlink; \
fuse_uid_t st_uid; \
fuse_gid_t st_gid; \
fuse_dev_t st_rdev; \
fuse_off_t st_size; \
struct fuse_timespec st_atim; \
struct fuse_timespec st_mtim; \
struct fuse_timespec st_ctim; \
fuse_blksize_t st_blksize; \
fuse_blkcnt_t st_blocks; \
struct fuse_timespec st_birthtim;
#define FSP_FUSE_STAT_EX_FIELD_DEFN \
FSP_FUSE_STAT_FIELD_DEFN \
uint32_t st_flags; \
uint32_t st_reserved32[3]; \
uint64_t st_reserved64[2];
#if defined(_WIN64) || defined(_WIN32)
typedef uint32_t fuse_uid_t;
typedef uint32_t fuse_gid_t;
typedef int32_t fuse_pid_t;
typedef uint32_t fuse_dev_t;
typedef uint64_t fuse_ino_t;
typedef uint32_t fuse_mode_t;
typedef uint16_t fuse_nlink_t;
typedef int64_t fuse_off_t;
#if defined(_WIN64)
typedef uint64_t fuse_fsblkcnt_t;
typedef uint64_t fuse_fsfilcnt_t;
#else
typedef uint32_t fuse_fsblkcnt_t;
typedef uint32_t fuse_fsfilcnt_t;
#endif
typedef int32_t fuse_blksize_t;
typedef int64_t fuse_blkcnt_t;
#if defined(_WIN64)
struct fuse_utimbuf
{
int64_t actime;
int64_t modtime;
};
struct fuse_timespec
{
int64_t tv_sec;
int64_t tv_nsec;
};
#else
struct fuse_utimbuf
{
int32_t actime;
int32_t modtime;
};
struct fuse_timespec
{
int32_t tv_sec;
int32_t tv_nsec;
};
#endif
#if !defined(FSP_FUSE_USE_STAT_EX)
struct fuse_stat
{
FSP_FUSE_STAT_FIELD_DEFN
};
#else
struct fuse_stat
{
FSP_FUSE_STAT_EX_FIELD_DEFN
};
#endif
#if defined(_WIN64)
struct fuse_statvfs
{
uint64_t f_bsize;
uint64_t f_frsize;
fuse_fsblkcnt_t f_blocks;
fuse_fsblkcnt_t f_bfree;
fuse_fsblkcnt_t f_bavail;
fuse_fsfilcnt_t f_files;
fuse_fsfilcnt_t f_ffree;
fuse_fsfilcnt_t f_favail;
uint64_t f_fsid;
uint64_t f_flag;
uint64_t f_namemax;
};
#else
struct fuse_statvfs
{
uint32_t f_bsize;
uint32_t f_frsize;
fuse_fsblkcnt_t f_blocks;
fuse_fsblkcnt_t f_bfree;
fuse_fsblkcnt_t f_bavail;
fuse_fsfilcnt_t f_files;
fuse_fsfilcnt_t f_ffree;
fuse_fsfilcnt_t f_favail;
uint32_t f_fsid;
uint32_t f_flag;
uint32_t f_namemax;
};
#endif
struct fuse_flock
{
int16_t l_type;
int16_t l_whence;
fuse_off_t l_start;
fuse_off_t l_len;
fuse_pid_t l_pid;
};
#if defined(WINFSP_DLL_INTERNAL)
#define FSP_FUSE_ENV_INIT \
{ \
'W', \
MemAlloc, MemFree, \
fsp_fuse_daemonize, \
fsp_fuse_set_signal_handlers, \
0/*conv_to_win_path*/, \
0/*winpid_to_pid*/, \
{ 0 }, \
}
#else
#define FSP_FUSE_ENV_INIT \
{ \
'W', \
malloc, free, \
fsp_fuse_daemonize, \
fsp_fuse_set_signal_handlers, \
0/*conv_to_win_path*/, \
0/*winpid_to_pid*/, \
{ 0 }, \
}
#endif
#elif defined(__CYGWIN__)
#include <fcntl.h>
#include <pthread.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <sys/types.h>
#include <utime.h>
#define fuse_uid_t uid_t
#define fuse_gid_t gid_t
#define fuse_pid_t pid_t
#define fuse_dev_t dev_t
#define fuse_ino_t ino_t
#define fuse_mode_t mode_t
#define fuse_nlink_t nlink_t
#define fuse_off_t off_t
#define fuse_fsblkcnt_t fsblkcnt_t
#define fuse_fsfilcnt_t fsfilcnt_t
#define fuse_blksize_t blksize_t
#define fuse_blkcnt_t blkcnt_t
#define fuse_utimbuf utimbuf
#define fuse_timespec timespec
#if !defined(FSP_FUSE_USE_STAT_EX)
#define fuse_stat stat
#else
struct fuse_stat
{
FSP_FUSE_STAT_EX_FIELD_DEFN
};
#endif
#define fuse_statvfs statvfs
#define fuse_flock flock
#define FSP_FUSE_ENV_INIT \
{ \
'C', \
malloc, free, \
fsp_fuse_daemonize, \
fsp_fuse_set_signal_handlers, \
fsp_fuse_conv_to_win_path, \
fsp_fuse_winpid_to_pid, \
{ 0 }, \
}
/*
* Note that long is 8 bytes long in Cygwin64 and 4 bytes long in Win64.
* For this reason we avoid using long anywhere in these headers.
*/
#else
#error unsupported environment
#endif
struct fuse_stat_ex
{
FSP_FUSE_STAT_EX_FIELD_DEFN
};
struct fsp_fuse_env
{
unsigned environment;
void *(*memalloc)(size_t);
void (*memfree)(void *);
int (*daemonize)(int);
int (*set_signal_handlers)(void *);
char *(*conv_to_win_path)(const char *);
fuse_pid_t (*winpid_to_pid)(uint32_t);
void (*reserved[2])();
};
FSP_FUSE_API void FSP_FUSE_API_NAME(fsp_fuse_signal_handler)(int sig);
#if defined(_WIN64) || defined(_WIN32)
static inline int fsp_fuse_daemonize(int foreground)
{
(void)foreground;
return 0;
}
static inline int fsp_fuse_set_signal_handlers(void *se)
{
(void)se;
return 0;
}
#elif defined(__CYGWIN__)
static inline int fsp_fuse_daemonize(int foreground)
{
int daemon(int nochdir, int noclose);
int chdir(const char *path);
if (!foreground)
{
if (-1 == daemon(0, 0))
return -1;
}
else
chdir("/");
return 0;
}
static inline void *fsp_fuse_signal_thread(void *psigmask)
{
int sig;
if (0 == sigwait((sigset_t *)psigmask, &sig))
FSP_FUSE_API_CALL(fsp_fuse_signal_handler)(sig);
return 0;
}
static inline int fsp_fuse_set_signal_handlers(void *se)
{
#define FSP_FUSE_SET_SIGNAL_HANDLER(sig, newha)\
if (-1 != sigaction((sig), 0, &oldsa) &&\
oldsa.sa_handler == (se ? SIG_DFL : (newha)))\
{\
newsa.sa_handler = se ? (newha) : SIG_DFL;\
sigaction((sig), &newsa, 0);\
}
#define FSP_FUSE_SIGADDSET(sig)\
if (-1 != sigaction((sig), 0, &oldsa) &&\
oldsa.sa_handler == SIG_DFL)\
sigaddset(&sigmask, (sig));
static sigset_t sigmask;
static pthread_t sigthr;
struct sigaction oldsa, newsa;
// memset instead of initializer to avoid GCC -Wmissing-field-initializers warning
memset(&newsa, 0, sizeof newsa);
if (0 != se)
{
if (0 == sigthr)
{
FSP_FUSE_SET_SIGNAL_HANDLER(SIGPIPE, SIG_IGN);
sigemptyset(&sigmask);
FSP_FUSE_SIGADDSET(SIGHUP);
FSP_FUSE_SIGADDSET(SIGINT);
FSP_FUSE_SIGADDSET(SIGTERM);
if (0 != pthread_sigmask(SIG_BLOCK, &sigmask, 0))
return -1;
if (0 != pthread_create(&sigthr, 0, fsp_fuse_signal_thread, &sigmask))
return -1;
}
}
else
{
if (0 != sigthr)
{
pthread_cancel(sigthr);
pthread_join(sigthr, 0);
sigthr = 0;
if (0 != pthread_sigmask(SIG_UNBLOCK, &sigmask, 0))
return -1;
sigemptyset(&sigmask);
FSP_FUSE_SET_SIGNAL_HANDLER(SIGPIPE, SIG_IGN);
}
}
return 0;
#undef FSP_FUSE_SIGADDSET
#undef FSP_FUSE_SET_SIGNAL_HANDLER
}
static inline char *fsp_fuse_conv_to_win_path(const char *path)
{
void *cygwin_create_path(unsigned, const void *);
return (char *)cygwin_create_path(
0/*CCP_POSIX_TO_WIN_A*/ | 0x100/*CCP_RELATIVE*/,
path);
}
static inline fuse_pid_t fsp_fuse_winpid_to_pid(uint32_t winpid)
{
pid_t cygwin_winpid_to_pid(int winpid);
pid_t pid = cygwin_winpid_to_pid(winpid);
return -1 != pid ? pid : (fuse_pid_t)winpid;
}
#endif
static inline struct fsp_fuse_env *fsp_fuse_env(void)
{
static struct fsp_fuse_env env = FSP_FUSE_ENV_INIT;
return &env;
}
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,338 @@
/**
* @file fuse3/fuse.h
* WinFsp FUSE3 compatible API.
*
* This file is derived from libfuse/include/fuse.h:
* FUSE: Filesystem in Userspace
* Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
*
* @copyright 2015-2025 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
*
* You can redistribute it and/or modify it under the terms of the GNU
* General Public License version 3 as published by the Free Software
* Foundation.
*
* Licensees holding a valid commercial license may use this software
* in accordance with the commercial license agreement provided in
* conjunction with the software. The terms and conditions of any such
* commercial license agreement shall govern, supersede, and render
* ineffective any application of the GPLv3 license to this software,
* notwithstanding of any reference thereto in the software or
* associated repository.
*/
#ifndef FUSE_H_
#define FUSE_H_
#include "fuse_common.h"
#ifdef __cplusplus
extern "C" {
#endif
struct fuse3;
enum fuse3_readdir_flags
{
FUSE_READDIR_PLUS = (1 << 0),
};
enum fuse3_fill_dir_flags
{
FUSE_FILL_DIR_PLUS = (1 << 1),
};
typedef int (*fuse3_fill_dir_t)(void *buf, const char *name,
const struct fuse_stat *stbuf, fuse_off_t off,
enum fuse3_fill_dir_flags flags);
struct fuse3_config
{
int set_gid;
unsigned int gid;
int set_uid;
unsigned int uid;
int set_mode;
unsigned int umask;
double entry_timeout;
double negative_timeout;
double attr_timeout;
int intr;
int intr_signal;
int remember;
int hard_remove;
int use_ino;
int readdir_ino;
int direct_io;
int kernel_cache;
int auto_cache;
int ac_attr_timeout_set;
double ac_attr_timeout;
int nullpath_ok;
/* private */
int show_help;
char *modules;
int debug;
};
struct fuse3_operations
{
/* S - supported by WinFsp */
/* S */ int (*getattr)(const char *path, struct fuse_stat *stbuf,
struct fuse3_file_info *fi);
/* S */ int (*readlink)(const char *path, char *buf, size_t size);
/* S */ int (*mknod)(const char *path, fuse_mode_t mode, fuse_dev_t dev);
/* S */ int (*mkdir)(const char *path, fuse_mode_t mode);
/* S */ int (*unlink)(const char *path);
/* S */ int (*rmdir)(const char *path);
/* S */ int (*symlink)(const char *dstpath, const char *srcpath);
/* S */ int (*rename)(const char *oldpath, const char *newpath, unsigned int flags);
/* _ */ int (*link)(const char *srcpath, const char *dstpath);
/* S */ int (*chmod)(const char *path, fuse_mode_t mode,
struct fuse3_file_info *fi);
/* S */ int (*chown)(const char *path, fuse_uid_t uid, fuse_gid_t gid,
struct fuse3_file_info *fi);
/* S */ int (*truncate)(const char *path, fuse_off_t size,
struct fuse3_file_info *fi);
/* S */ int (*open)(const char *path, struct fuse3_file_info *fi);
/* S */ int (*read)(const char *path, char *buf, size_t size, fuse_off_t off,
struct fuse3_file_info *fi);
/* S */ int (*write)(const char *path, const char *buf, size_t size, fuse_off_t off,
struct fuse3_file_info *fi);
/* S */ int (*statfs)(const char *path, struct fuse_statvfs *stbuf);
/* S */ int (*flush)(const char *path, struct fuse3_file_info *fi);
/* S */ int (*release)(const char *path, struct fuse3_file_info *fi);
/* S */ int (*fsync)(const char *path, int datasync, struct fuse3_file_info *fi);
/* S */ int (*setxattr)(const char *path, const char *name, const char *value, size_t size,
int flags);
/* S */ int (*getxattr)(const char *path, const char *name, char *value, size_t size);
/* S */ int (*listxattr)(const char *path, char *namebuf, size_t size);
/* S */ int (*removexattr)(const char *path, const char *name);
/* S */ int (*opendir)(const char *path, struct fuse3_file_info *fi);
/* S */ int (*readdir)(const char *path, void *buf, fuse3_fill_dir_t filler, fuse_off_t off,
struct fuse3_file_info *fi, enum fuse3_readdir_flags);
/* S */ int (*releasedir)(const char *path, struct fuse3_file_info *fi);
/* S */ int (*fsyncdir)(const char *path, int datasync, struct fuse3_file_info *fi);
/* S */ void *(*init)(struct fuse3_conn_info *conn,
struct fuse3_config *conf);
/* S */ void (*destroy)(void *data);
/* _ */ int (*access)(const char *path, int mask);
/* S */ int (*create)(const char *path, fuse_mode_t mode, struct fuse3_file_info *fi);
/* _ */ int (*lock)(const char *path,
struct fuse3_file_info *fi, int cmd, struct fuse_flock *lock);
/* S */ int (*utimens)(const char *path, const struct fuse_timespec tv[2],
struct fuse3_file_info *fi);
/* _ */ int (*bmap)(const char *path, size_t blocksize, uint64_t *idx);
/* S */ int (*ioctl)(const char *path, int cmd, void *arg, struct fuse3_file_info *fi,
unsigned int flags, void *data);
/* _ */ int (*poll)(const char *path, struct fuse3_file_info *fi,
struct fuse3_pollhandle *ph, unsigned *reventsp);
/* _ */ int (*write_buf)(const char *path,
struct fuse3_bufvec *buf, fuse_off_t off, struct fuse3_file_info *fi);
/* _ */ int (*read_buf)(const char *path,
struct fuse3_bufvec **bufp, size_t size, fuse_off_t off, struct fuse3_file_info *fi);
/* _ */ int (*flock)(const char *path, struct fuse3_file_info *, int op);
/* _ */ int (*fallocate)(const char *path, int mode, fuse_off_t off, fuse_off_t len,
struct fuse3_file_info *fi);
};
struct fuse3_context
{
struct fuse3 *fuse;
fuse_uid_t uid;
fuse_gid_t gid;
fuse_pid_t pid;
void *private_data;
fuse_mode_t umask;
};
#define fuse_main(argc, argv, ops, data)\
fuse3_main_real(argc, argv, ops, sizeof *(ops), data)
FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse3_main_real)(struct fsp_fuse_env *env,
int argc, char *argv[],
const struct fuse3_operations *ops, size_t opsize, void *data);
FSP_FUSE_API void FSP_FUSE_API_NAME(fsp_fuse3_lib_help)(struct fsp_fuse_env *env,
struct fuse_args *args);
FSP_FUSE_API struct fuse3 *FSP_FUSE_API_NAME(fsp_fuse3_new_30)(struct fsp_fuse_env *env,
struct fuse_args *args,
const struct fuse3_operations *ops, size_t opsize, void *data);
FSP_FUSE_API struct fuse3 *FSP_FUSE_API_NAME(fsp_fuse3_new)(struct fsp_fuse_env *env,
struct fuse_args *args,
const struct fuse3_operations *ops, size_t opsize, void *data);
FSP_FUSE_API void FSP_FUSE_API_NAME(fsp_fuse3_destroy)(struct fsp_fuse_env *env,
struct fuse3 *f);
FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse3_mount)(struct fsp_fuse_env *env,
struct fuse3 *f, const char *mountpoint);
FSP_FUSE_API void FSP_FUSE_API_NAME(fsp_fuse3_unmount)(struct fsp_fuse_env *env,
struct fuse3 *f);
FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse3_loop)(struct fsp_fuse_env *env,
struct fuse3 *f);
FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse3_loop_mt_31)(struct fsp_fuse_env *env,
struct fuse3 *f, int clone_fd);
FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse3_loop_mt)(struct fsp_fuse_env *env,
struct fuse3 *f, struct fuse3_loop_config *config);
FSP_FUSE_API void FSP_FUSE_API_NAME(fsp_fuse3_exit)(struct fsp_fuse_env *env,
struct fuse3 *f);
FSP_FUSE_API struct fuse3_context *FSP_FUSE_API_NAME(fsp_fuse3_get_context)(struct fsp_fuse_env *env);
FSP_FUSE_SYM(
int fuse3_main_real(int argc, char *argv[],
const struct fuse3_operations *ops, size_t opsize, void *data),
{
return FSP_FUSE_API_CALL(fsp_fuse3_main_real)
(fsp_fuse_env(), argc, argv, ops, opsize, data);
})
FSP_FUSE_SYM(
void fuse3_lib_help(struct fuse_args *args),
{
FSP_FUSE_API_CALL(fsp_fuse3_lib_help)
(fsp_fuse_env(), args);
})
#if FUSE_USE_VERSION == 30
FSP_FUSE_SYM(
struct fuse3 *fuse3_new_30(struct fuse_args *args,
const struct fuse3_operations *ops, size_t opsize, void *data),
{
return FSP_FUSE_API_CALL(fsp_fuse3_new_30)
(fsp_fuse_env(), args, ops, opsize, data);
})
#define fuse_new(args, op, size, data)\
fuse3_new_30(args, op, size, data)
#else
FSP_FUSE_SYM(
struct fuse3 *fuse3_new(struct fuse_args *args,
const struct fuse3_operations *ops, size_t opsize, void *data),
{
return FSP_FUSE_API_CALL(fsp_fuse3_new)
(fsp_fuse_env(), args, ops, opsize, data);
})
#endif
FSP_FUSE_SYM(
void fuse3_destroy(struct fuse3 *f),
{
FSP_FUSE_API_CALL(fsp_fuse3_destroy)
(fsp_fuse_env(), f);
})
FSP_FUSE_SYM(
int fuse3_mount(struct fuse3 *f, const char *mountpoint),
{
return FSP_FUSE_API_CALL(fsp_fuse3_mount)
(fsp_fuse_env(), f, mountpoint);
})
FSP_FUSE_SYM(
void fuse3_unmount(struct fuse3 *f),
{
FSP_FUSE_API_CALL(fsp_fuse3_unmount)
(fsp_fuse_env(), f);
})
FSP_FUSE_SYM(
int fuse3_loop(struct fuse3 *f),
{
return FSP_FUSE_API_CALL(fsp_fuse3_loop)
(fsp_fuse_env(), f);
})
#if FUSE_USE_VERSION < 32
FSP_FUSE_SYM(
int fuse3_loop_mt_31(struct fuse3 *f, int clone_fd),
{
return FSP_FUSE_API_CALL(fsp_fuse3_loop_mt_31)
(fsp_fuse_env(), f, clone_fd);
})
#define fuse_loop_mt(f, clone_fd)\
fuse3_loop_mt_31(f, clone_fd)
#else
FSP_FUSE_SYM(
int fuse3_loop_mt(struct fuse3 *f, struct fuse3_loop_config *config),
{
return FSP_FUSE_API_CALL(fsp_fuse3_loop_mt)
(fsp_fuse_env(), f, config);
})
#endif
FSP_FUSE_SYM(
void fuse3_exit(struct fuse3 *f),
{
FSP_FUSE_API_CALL(fsp_fuse3_exit)
(fsp_fuse_env(), f);
})
FSP_FUSE_SYM(
struct fuse3_context *fuse3_get_context(void),
{
return FSP_FUSE_API_CALL(fsp_fuse3_get_context)
(fsp_fuse_env());
})
FSP_FUSE_SYM(
int fuse3_getgroups(int size, fuse_gid_t list[]),
{
(void)size;
(void)list;
return -ENOSYS;
})
FSP_FUSE_SYM(
int fuse3_interrupted(void),
{
return 0;
})
FSP_FUSE_SYM(
int fuse3_invalidate_path(struct fuse3 *f, const char *path),
{
(void)f;
(void)path;
return -ENOENT;
})
FSP_FUSE_SYM(
int fuse3_notify_poll(struct fuse3_pollhandle *ph),
{
(void)ph;
return 0;
})
FSP_FUSE_SYM(
int fuse3_start_cleanup_thread(struct fuse3 *f),
{
(void)f;
return 0;
})
FSP_FUSE_SYM(
void fuse3_stop_cleanup_thread(struct fuse3 *f),
{
(void)f;
})
FSP_FUSE_SYM(
int fuse3_clean_cache(struct fuse3 *f),
{
(void)f;
return 600;
})
FSP_FUSE_SYM(
struct fuse3_session *fuse3_get_session(struct fuse3 *f),
{
return (struct fuse3_session *)f;
})
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,238 @@
/**
* @file fuse3/fuse_common.h
* WinFsp FUSE3 compatible API.
*
* This file is derived from libfuse/include/fuse_common.h:
* FUSE: Filesystem in Userspace
* Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
*
* @copyright 2015-2025 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
*
* You can redistribute it and/or modify it under the terms of the GNU
* General Public License version 3 as published by the Free Software
* Foundation.
*
* Licensees holding a valid commercial license may use this software
* in accordance with the commercial license agreement provided in
* conjunction with the software. The terms and conditions of any such
* commercial license agreement shall govern, supersede, and render
* ineffective any application of the GPLv3 license to this software,
* notwithstanding of any reference thereto in the software or
* associated repository.
*/
#ifndef FUSE_COMMON_H_
#define FUSE_COMMON_H_
#include "winfsp_fuse.h"
#if !defined(WINFSP_DLL_INTERNAL)
#include "fuse_opt.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define FUSE_MAJOR_VERSION 3
#define FUSE_MINOR_VERSION 2
#define FUSE_MAKE_VERSION(maj, min) ((maj) * 10 + (min))
#define FUSE_VERSION FUSE_MAKE_VERSION(FUSE_MAJOR_VERSION, FUSE_MINOR_VERSION)
#define FUSE_CAP_ASYNC_READ (1 << 0)
#define FUSE_CAP_POSIX_LOCKS (1 << 1)
#define FUSE_CAP_ATOMIC_O_TRUNC (1 << 3)
#define FUSE_CAP_EXPORT_SUPPORT (1 << 4)
#define FUSE_CAP_DONT_MASK (1 << 6)
#define FUSE_CAP_SPLICE_WRITE (1 << 7)
#define FUSE_CAP_SPLICE_MOVE (1 << 8)
#define FUSE_CAP_SPLICE_READ (1 << 9)
#define FUSE_CAP_FLOCK_LOCKS (1 << 10)
#define FUSE_CAP_IOCTL_DIR (1 << 11)
#define FUSE_CAP_AUTO_INVAL_DATA (1 << 12)
#define FUSE_CAP_READDIRPLUS (1 << 13)
#define FUSE_CAP_READDIRPLUS_AUTO (1 << 14)
#define FUSE_CAP_ASYNC_DIO (1 << 15)
#define FUSE_CAP_WRITEBACK_CACHE (1 << 16)
#define FUSE_CAP_NO_OPEN_SUPPORT (1 << 17)
#define FUSE_CAP_PARALLEL_DIROPS (1 << 18)
#define FUSE_CAP_POSIX_ACL (1 << 19)
#define FUSE_CAP_HANDLE_KILLPRIV (1 << 20)
#define FUSE_CAP_ALLOCATE (1 << 27) /* reserved (OSXFUSE) */
#define FUSE_CAP_EXCHANGE_DATA (1 << 28) /* reserved (OSXFUSE) */
#define FUSE_CAP_CASE_INSENSITIVE (1 << 29) /* file system is case insensitive */
#define FUSE_CAP_VOL_RENAME (1 << 30) /* reserved (OSXFUSE) */
#define FUSE_CAP_XTIMES (1 << 31) /* reserved (OSXFUSE) */
#define FSP_FUSE_CAP_CASE_INSENSITIVE FUSE_CAP_CASE_INSENSITIVE
#define FUSE_IOCTL_COMPAT (1 << 0)
#define FUSE_IOCTL_UNRESTRICTED (1 << 1)
#define FUSE_IOCTL_RETRY (1 << 2)
#define FUSE_IOCTL_DIR (1 << 4)
#define FUSE_IOCTL_MAX_IOV 256
#define FUSE_BUFVEC_INIT(s) \
((struct fuse3_bufvec){ 1, 0, 0, { {s, (enum fuse3_buf_flags)0, 0, -1, 0} } })
struct fuse3_file_info
{
int flags;
unsigned int writepage:1;
unsigned int direct_io:1;
unsigned int keep_cache:1;
unsigned int flush:1;
unsigned int nonseekable:1;
unsigned int flock_release:1;
unsigned int padding:27;
uint64_t fh;
uint64_t lock_owner;
uint32_t poll_events;
};
struct fuse3_loop_config
{
int clone_fd;
unsigned int max_idle_threads;
};
struct fuse3_conn_info
{
unsigned proto_major;
unsigned proto_minor;
unsigned max_write;
unsigned max_read;
unsigned max_readahead;
unsigned capable;
unsigned want;
unsigned max_background;
unsigned congestion_threshold;
unsigned time_gran;
unsigned reserved[22];
};
enum fuse3_buf_flags
{
FUSE_BUF_IS_FD = (1 << 1),
FUSE_BUF_FD_SEEK = (1 << 2),
FUSE_BUF_FD_RETRY = (1 << 3),
};
enum fuse3_buf_copy_flags
{
FUSE_BUF_NO_SPLICE = (1 << 1),
FUSE_BUF_FORCE_SPLICE = (1 << 2),
FUSE_BUF_SPLICE_MOVE = (1 << 3),
FUSE_BUF_SPLICE_NONBLOCK = (1 << 4),
};
struct fuse3_buf
{
size_t size;
enum fuse3_buf_flags flags;
void *mem;
int fd;
fuse_off_t pos;
};
struct fuse3_bufvec
{
size_t count;
size_t idx;
size_t off;
struct fuse3_buf buf[1];
};
struct fuse3_session;
struct fuse3_pollhandle;
struct fuse3_conn_info_opts;
FSP_FUSE_API struct fuse3_conn_info_opts *FSP_FUSE_API_NAME(fsp_fuse3_parse_conn_info_opts)(
struct fsp_fuse_env *env,
struct fuse_args *args);
FSP_FUSE_API void FSP_FUSE_API_NAME(fsp_fuse3_apply_conn_info_opts)(struct fsp_fuse_env *env,
struct fuse3_conn_info_opts *opts, struct fuse3_conn_info *conn);
FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse3_version)(struct fsp_fuse_env *env);
FSP_FUSE_API const char *FSP_FUSE_API_NAME(fsp_fuse3_pkgversion)(struct fsp_fuse_env *env);
FSP_FUSE_API int32_t FSP_FUSE_API_NAME(fsp_fuse_ntstatus_from_errno)(struct fsp_fuse_env *env,
int err);
FSP_FUSE_SYM(
struct fuse3_conn_info_opts* fuse3_parse_conn_info_opts(
struct fuse_args *args),
{
return FSP_FUSE_API_CALL(fsp_fuse3_parse_conn_info_opts)
(fsp_fuse_env(), args);
})
FSP_FUSE_SYM(
void fuse3_apply_conn_info_opts(
struct fuse3_conn_info_opts *opts, struct fuse3_conn_info *conn),
{
FSP_FUSE_API_CALL(fsp_fuse3_apply_conn_info_opts)
(fsp_fuse_env(), opts, conn);
})
FSP_FUSE_SYM(
int fuse3_version(void),
{
return FSP_FUSE_API_CALL(fsp_fuse3_version)
(fsp_fuse_env());
})
FSP_FUSE_SYM(
const char *fuse3_pkgversion(void),
{
return FSP_FUSE_API_CALL(fsp_fuse3_pkgversion)
(fsp_fuse_env());
})
FSP_FUSE_SYM(
void fuse3_pollhandle_destroy(struct fuse3_pollhandle *ph),
{
(void)ph;
})
FSP_FUSE_SYM(
size_t fuse3_buf_size(const struct fuse3_bufvec *bufv),
{
(void)bufv;
return 0;
})
FSP_FUSE_SYM(
ssize_t fuse3_buf_copy(struct fuse3_bufvec *dst, struct fuse3_bufvec *src,
enum fuse3_buf_copy_flags flags),
{
(void)dst;
(void)src;
(void)flags;
return 0;
})
FSP_FUSE_SYM(
int fuse3_daemonize(int foreground),
{
return fsp_fuse_daemonize(foreground);
})
FSP_FUSE_SYM(
int fuse3_set_signal_handlers(struct fuse3_session *se),
{
return fsp_fuse_set_signal_handlers(se);
})
FSP_FUSE_SYM(
void fuse3_remove_signal_handlers(struct fuse3_session *se),
{
(void)se;
fsp_fuse_set_signal_handlers(0);
})
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,23 @@
/**
* @file fuse3/fuse_opt.h
* WinFsp FUSE3 compatible API.
*
* @copyright 2015-2025 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
*
* You can redistribute it and/or modify it under the terms of the GNU
* General Public License version 3 as published by the Free Software
* Foundation.
*
* Licensees holding a valid commercial license may use this software
* in accordance with the commercial license agreement provided in
* conjunction with the software. The terms and conditions of any such
* commercial license agreement shall govern, supersede, and render
* ineffective any application of the GPLv3 license to this software,
* notwithstanding of any reference thereto in the software or
* associated repository.
*/
#include "../fuse/fuse_opt.h"

View File

@@ -0,0 +1,82 @@
/**
* @file fuse3/winfsp_fuse.h
* WinFsp FUSE3 compatible API.
*
* @copyright 2015-2025 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
*
* You can redistribute it and/or modify it under the terms of the GNU
* General Public License version 3 as published by the Free Software
* Foundation.
*
* Licensees holding a valid commercial license may use this software
* in accordance with the commercial license agreement provided in
* conjunction with the software. The terms and conditions of any such
* commercial license agreement shall govern, supersede, and render
* ineffective any application of the GPLv3 license to this software,
* notwithstanding of any reference thereto in the software or
* associated repository.
*/
#ifndef FUSE3_WINFSP_FUSE_H_INCLUDED
#define FUSE3_WINFSP_FUSE_H_INCLUDED
#include "../fuse/winfsp_fuse.h"
#if defined(_WIN64) || defined(_WIN32)
typedef intptr_t ssize_t;
#endif
#if !defined(WINFSP_DLL_INTERNAL)
#define fuse3 fuse
#define fuse3_apply_conn_info_opts fuse_apply_conn_info_opts
#define fuse3_buf fuse_buf
#define fuse3_buf_copy fuse_buf_copy
#define fuse3_buf_copy_flags fuse_buf_copy_flags
#define fuse3_buf_flags fuse_buf_flags
#define fuse3_buf_size fuse_buf_size
#define fuse3_bufvec fuse_bufvec
#define fuse3_clean_cache fuse_clean_cache
#define fuse3_config fuse_config
#define fuse3_conn_info fuse_conn_info
#define fuse3_conn_info_opts fuse_conn_info_opts
#define fuse3_context fuse_context
#define fuse3_daemonize fuse_daemonize
#define fuse3_destroy fuse_destroy
#define fuse3_exit fuse_exit
#define fuse3_file_info fuse_file_info
#define fuse3_fill_dir_flags fuse_fill_dir_flags
#define fuse3_fill_dir_t fuse_fill_dir_t
#define fuse3_get_context fuse_get_context
#define fuse3_get_session fuse_get_session
#define fuse3_getgroups fuse_getgroups
#define fuse3_interrupted fuse_interrupted
#define fuse3_invalidate_path fuse_invalidate_path
#define fuse3_lib_help fuse_lib_help
#define fuse3_loop fuse_loop
#define fuse3_loop_config fuse_loop_config
#define fuse3_loop_mt fuse_loop_mt
#define fuse3_loop_mt_31 fuse_loop_mt_31
#define fuse3_main_real fuse_main_real
#define fuse3_mount fuse_mount
#define fuse3_new fuse_new
#define fuse3_new_30 fuse_new_30
#define fuse3_notify_poll fuse_notify_poll
#define fuse3_operations fuse_operations
#define fuse3_parse_conn_info_opts fuse_parse_conn_info_opts
#define fuse3_pkgversion fuse_pkgversion
#define fuse3_pollhandle fuse_pollhandle
#define fuse3_pollhandle_destroy fuse_pollhandle_destroy
#define fuse3_readdir_flags fuse_readdir_flags
#define fuse3_remove_signal_handlers fuse_remove_signal_handlers
#define fuse3_session fuse_session
#define fuse3_set_signal_handlers fuse_set_signal_handlers
#define fuse3_start_cleanup_thread fuse_start_cleanup_thread
#define fuse3_stop_cleanup_thread fuse_stop_cleanup_thread
#define fuse3_unmount fuse_unmount
#define fuse3_version fuse_version
#endif
#endif

View File

@@ -0,0 +1,812 @@
/**
* @file winfsp/fsctl.h
*
* @copyright 2015-2025 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
*
* You can redistribute it and/or modify it under the terms of the GNU
* General Public License version 3 as published by the Free Software
* Foundation.
*
* Licensees holding a valid commercial license may use this software
* in accordance with the commercial license agreement provided in
* conjunction with the software. The terms and conditions of any such
* commercial license agreement shall govern, supersede, and render
* ineffective any application of the GPLv3 license to this software,
* notwithstanding of any reference thereto in the software or
* associated repository.
*/
#ifndef WINFSP_FSCTL_H_INCLUDED
#define WINFSP_FSCTL_H_INCLUDED
#include <devioctl.h>
#ifdef __cplusplus
extern "C" {
#endif
/* static_assert is a C++11 feature, but seems to work with C on MSVC 2015 */
#if defined(WINFSP_SYS_INTERNAL) || defined(WINFSP_DLL_INTERNAL)
#define FSP_FSCTL_STATIC_ASSERT(e,m) static_assert(e,m)
#else
#define FSP_FSCTL_STATIC_ASSERT(e,m) static_assert(1,"")
#endif
#define FSP_FSCTL_STR(x) FSP_FSCTL_STR_(x)
#define FSP_FSCTL_STR_(x) #x
#if defined(MyProductName)
#define FSP_FSCTL_PRODUCT_NAME FSP_FSCTL_STR(MyProductName)
#else
#define FSP_FSCTL_PRODUCT_NAME "WinFsp"
#endif
#if defined(MyProductFileName)
#define FSP_FSCTL_PRODUCT_FILE_NAME FSP_FSCTL_STR(MyProductFileName)
#else
#define FSP_FSCTL_PRODUCT_FILE_NAME "winfsp"
#endif
#define FSP_FSCTL_DRIVER_NAME FSP_FSCTL_PRODUCT_NAME
#define FSP_FSCTL_DISK_DEVICE_NAME FSP_FSCTL_DRIVER_NAME ".Disk"
#define FSP_FSCTL_NET_DEVICE_NAME FSP_FSCTL_DRIVER_NAME ".Net"
#define FSP_FSCTL_MUP_DEVICE_NAME FSP_FSCTL_DRIVER_NAME ".Mup"
#if defined(MyFspFsctlDeviceClassGuid)
extern const __declspec(selectany) GUID FspFsctlDeviceClassGuid = MyFspFsctlDeviceClassGuid;
#else
extern const __declspec(selectany) GUID FspFsctlDeviceClassGuid =
{ 0x6f9d25fa, 0x6dee, 0x4a9d, { 0x80, 0xf5, 0xe9, 0x8e, 0x14, 0xf3, 0x5e, 0x54 } };
#endif
#if defined(MyFspFsvrtDeviceClassGuid)
extern const __declspec(selectany) GUID FspFsvrtDeviceClassGuid = MyFspFsvrtDeviceClassGuid;
#else
extern const __declspec(selectany) GUID FspFsvrtDeviceClassGuid =
{ 0xb48171c3, 0xdd50, 0x4852, { 0x83, 0xa3, 0x34, 0x4c, 0x50, 0xd9, 0x3b, 0x17 } };
#endif
/* locations */
#define FSP_FSCTL_PRODUCT_REGKEY "Software\\" FSP_FSCTL_PRODUCT_NAME
#define FSP_FSCTL_PRODUCT_REGKEY_WOW64 KEY_WOW64_32KEY
#if defined(_ARM64_)
#define FSP_FSCTL_PRODUCT_FULL_REGKEY "Software\\WOW6432Node\\" FSP_FSCTL_PRODUCT_NAME
#define FSP_FSCTL_PRODUCT_FILE_ARCH "a64"
#elif defined(_AMD64_)
#define FSP_FSCTL_PRODUCT_FULL_REGKEY "Software\\WOW6432Node\\" FSP_FSCTL_PRODUCT_NAME
#define FSP_FSCTL_PRODUCT_FILE_ARCH "x64"
#elif defined(_X86_)
#define FSP_FSCTL_PRODUCT_FULL_REGKEY "Software\\" FSP_FSCTL_PRODUCT_NAME
#define FSP_FSCTL_PRODUCT_FILE_ARCH "x86"
#else
#error unknown architecture
#endif
/* 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_MOUNTDEV \
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'M', METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSP_FSCTL_MOUNTMGR \
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'm', METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSP_FSCTL_VOLUME_NAME \
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'N', METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSP_FSCTL_VOLUME_LIST \
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'L', METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSP_FSCTL_TRANSACT \
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'T', METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSP_IOCTL_TRANSACT \
CTL_CODE(0x8000 | ('F'<<8) | 'W', 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_IOCTL_TRANSACT_BATCH \
CTL_CODE(0x8000 | ('F'<<8) | 'W', 0x800 + 't', METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSP_FSCTL_STOP \
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'S', METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSP_FSCTL_STOP0 \
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 's', METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSP_FSCTL_NOTIFY \
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'n', METHOD_NEITHER, FILE_ANY_ACCESS)
#define FSP_FSCTL_UNLOAD \
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'U', METHOD_NEITHER, FILE_ANY_ACCESS)
/* fsctl internal device codes (usable only in-kernel) */
#define FSP_FSCTL_TRANSACT_INTERNAL \
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'I', METHOD_NEITHER, FILE_ANY_ACCESS)
#define FSP_IOCTL_TRANSACT_INTERNAL \
CTL_CODE(0x8000 | ('F'<<8) | 'W', 0x800 + 'I', METHOD_BUFFERED, FILE_ANY_ACCESS)
/* fsvol device codes */
#define FSP_FSCTL_QUERY_WINFSP \
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + '?', METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSP_FSCTL_VOLUME_PARAMS_PREFIX "\\VolumeParams="
#define FSP_FSCTL_VOLUME_NAME_SIZE (64 * sizeof(WCHAR))
#define FSP_FSCTL_VOLUME_PREFIX_SIZE (192 * sizeof(WCHAR))
#define FSP_FSCTL_VOLUME_FSNAME_SIZE (16 * sizeof(WCHAR))
#define FSP_FSCTL_VOLUME_NAME_SIZEMAX (FSP_FSCTL_VOLUME_NAME_SIZE + FSP_FSCTL_VOLUME_PREFIX_SIZE)
FSP_FSCTL_STATIC_ASSERT(FSP_FSCTL_VOLUME_NAME_SIZEMAX <= 260 * sizeof(WCHAR),
"Max volume name size is greater than MAX_PATH.");
#define FSP_FSCTL_TRANSACT_PATH_SIZEMAX (1024 * sizeof(WCHAR))
#define FSP_FSCTL_TRANSACT_REQ_SIZEMAX (16 * 1024 - 64) /* 64: size for internal request header */
#define FSP_FSCTL_TRANSACT_RSP_SIZEMAX (16 * 1024)
#define FSP_FSCTL_TRANSACT_REQ_BUFFER_SIZEMAX (FSP_FSCTL_TRANSACT_REQ_SIZEMAX - sizeof(FSP_FSCTL_TRANSACT_REQ))
#define FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMAX (FSP_FSCTL_TRANSACT_RSP_SIZEMAX - sizeof(FSP_FSCTL_TRANSACT_RSP))
#define FSP_FSCTL_TRANSACT_BATCH_BUFFER_SIZEMIN (64 * 1024)
#define FSP_FSCTL_TRANSACT_BUFFER_SIZEMIN FSP_FSCTL_TRANSACT_REQ_SIZEMAX
#define FSP_FSCTL_TRANSACT_REQ_TOKEN_HANDLE(T) ((HANDLE)((UINT_PTR)((T) & 0xffffffff)))
#define FSP_FSCTL_TRANSACT_REQ_TOKEN_PID(T) ((UINT32)(((T) >> 32) & 0xffffffff))
#define FSP_FSCTL_DEVICECONTROL_SIZEMAX (4 * 1024) /* must be < FSP_FSCTL_TRANSACT_{REQ,RSP}_SIZEMAX */
/* marshalling */
#pragma warning(push)
#pragma warning(disable:4200 4201) /* zero-sized array in struct/union; nameless 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,
FspFsctlTransactQueryStreamInformationKind,
FspFsctlTransactKindCount,
};
enum
{
FspFsctlTransactTimeoutMinimum = 1000,
FspFsctlTransactTimeoutMaximum = 10000,
FspFsctlTransactTimeoutDefault = 1000, /* DEPRECATED: default is unspecified */
FspFsctlIrpTimeoutMinimum = 60000,
FspFsctlIrpTimeoutMaximum = 600000,
FspFsctlIrpTimeoutDefault = 300000,
FspFsctlIrpTimeoutDebug = 142, /* special value for IRP timeout testing */
FspFsctlIrpCapacityMinimum = 100,
FspFsctlIrpCapacityMaximum = 1000,
FspFsctlIrpCapacityDefault = 1000,
};
#define FSP_FSCTL_VOLUME_PARAMS_V0_FIELD_DEFN\
UINT16 Version; /* set to 0 or sizeof(FSP_FSCTL_VOLUME_PARAMS) */\
/* 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; /* DEPRECATED: (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 */\
UINT32 ReparsePointsAccessCheck:1; /* file system performs reparse point access checks */\
UINT32 NamedStreams:1; /* file system supports named streams */\
UINT32 HardLinks:1; /* unimplemented; set to 0 */\
UINT32 ExtendedAttributes:1; /* file system supports extended attributes */\
UINT32 ReadOnlyVolume:1;\
/* kernel-mode flags */\
UINT32 PostCleanupWhenModifiedOnly:1; /* post Cleanup when a file was modified/deleted */\
UINT32 PassQueryDirectoryPattern:1; /* pass Pattern during QueryDirectory operations */\
UINT32 AlwaysUseDoubleBuffering:1;\
UINT32 PassQueryDirectoryFileName:1; /* pass FileName during QueryDirectory (GetDirInfoByName) */\
UINT32 FlushAndPurgeOnCleanup:1; /* keeps file off "standby" list */\
UINT32 DeviceControl:1; /* support user-mode ioctl handling */\
/* user-mode flags */\
UINT32 UmFileContextIsUserContext2:1; /* user mode: FileContext parameter is UserContext2 */\
UINT32 UmFileContextIsFullContext:1; /* user mode: FileContext parameter is FullContext */\
UINT32 UmNoReparsePointsDirCheck:1; /* user mode: no dir option check for reparse points */\
UINT32 UmReservedFlags:5;\
/* additional kernel-mode flags */\
UINT32 AllowOpenInKernelMode:1; /* allow kernel mode to open files when possible */\
UINT32 CasePreservedExtendedAttributes:1; /* preserve case of EA (default is UPPERCASE) */\
UINT32 WslFeatures:1; /* support features required for WSLinux */\
UINT32 DirectoryMarkerAsNextOffset:1; /* directory marker is next offset instead of last name */\
UINT32 RejectIrpPriorToTransact0:1; /* DEPRECATED: reject IRP's prior to FspFsctlTransact0 */\
UINT32 SupportsPosixUnlinkRename:1; /* file system supports POSIX-style unlink and rename */\
UINT32 PostDispositionWhenNecessaryOnly:1; /* post Disposition for dirs or READONLY attr check */\
UINT32 KmReservedFlags:1;\
WCHAR Prefix[FSP_FSCTL_VOLUME_PREFIX_SIZE / sizeof(WCHAR)]; /* UNC prefix (\Server\Share) */\
WCHAR FileSystemName[FSP_FSCTL_VOLUME_FSNAME_SIZE / sizeof(WCHAR)];
#define FSP_FSCTL_VOLUME_PARAMS_V1_FIELD_DEFN\
/* additional fields; specify .Version == sizeof(FSP_FSCTL_VOLUME_PARAMS) */\
UINT32 VolumeInfoTimeoutValid:1; /* VolumeInfoTimeout field is valid */\
UINT32 DirInfoTimeoutValid:1; /* DirInfoTimeout field is valid */\
UINT32 SecurityTimeoutValid:1; /* SecurityTimeout field is valid*/\
UINT32 StreamInfoTimeoutValid:1; /* StreamInfoTimeout field is valid */\
UINT32 EaTimeoutValid:1; /* EaTimeout field is valid */\
UINT32 KmAdditionalReservedFlags:27;\
UINT32 VolumeInfoTimeout; /* volume info timeout (millis); overrides FileInfoTimeout */\
UINT32 DirInfoTimeout; /* dir info timeout (millis); overrides FileInfoTimeout */\
UINT32 SecurityTimeout; /* security info timeout (millis); overrides FileInfoTimeout */\
UINT32 StreamInfoTimeout; /* stream info timeout (millis); overrides FileInfoTimeout */\
UINT32 EaTimeout; /* EA timeout (millis); overrides FileInfoTimeout */\
UINT32 FsextControlCode;\
UINT32 Reserved32[1];\
UINT64 Reserved64[2];
typedef struct
{
FSP_FSCTL_VOLUME_PARAMS_V0_FIELD_DEFN
} FSP_FSCTL_VOLUME_PARAMS_V0;
FSP_FSCTL_STATIC_ASSERT(456 == sizeof(FSP_FSCTL_VOLUME_PARAMS_V0),
"sizeof(FSP_FSCTL_VOLUME_PARAMS_V0) must be exactly 456.");
typedef struct
{
FSP_FSCTL_VOLUME_PARAMS_V0_FIELD_DEFN
FSP_FSCTL_VOLUME_PARAMS_V1_FIELD_DEFN
} FSP_FSCTL_VOLUME_PARAMS;
FSP_FSCTL_STATIC_ASSERT(504 == sizeof(FSP_FSCTL_VOLUME_PARAMS),
"sizeof(FSP_FSCTL_VOLUME_PARAMS) is currently 504. Update this assertion check if it changes.");
typedef struct
{
UINT64 TotalSize;
UINT64 FreeSize;
UINT16 VolumeLabelLength;
WCHAR VolumeLabel[32];
} FSP_FSCTL_VOLUME_INFO;
FSP_FSCTL_STATIC_ASSERT(88 == sizeof(FSP_FSCTL_VOLUME_INFO),
"sizeof(FSP_FSCTL_VOLUME_INFO) must be exactly 88.");
typedef struct
{
UINT32 FileAttributes;
UINT32 ReparseTag;
UINT64 AllocationSize;
UINT64 FileSize;
UINT64 CreationTime;
UINT64 LastAccessTime;
UINT64 LastWriteTime;
UINT64 ChangeTime;
UINT64 IndexNumber;
UINT32 HardLinks; /* unimplemented: set to 0 */
UINT32 EaSize;
} FSP_FSCTL_FILE_INFO;
FSP_FSCTL_STATIC_ASSERT(72 == sizeof(FSP_FSCTL_FILE_INFO),
"sizeof(FSP_FSCTL_FILE_INFO) must be exactly 72.");
typedef struct
{
FSP_FSCTL_FILE_INFO FileInfo;
PWSTR NormalizedName;
UINT16 NormalizedNameSize;
} FSP_FSCTL_OPEN_FILE_INFO;
typedef struct
{
UINT16 Size;
FSP_FSCTL_FILE_INFO FileInfo;
union
{
UINT64 NextOffset;
UINT8 Padding[24];
/* make struct as big as FILE_ID_BOTH_DIR_INFORMATION; allows for in-place copying */
} DUMMYUNIONNAME;
WCHAR FileNameBuf[];
} FSP_FSCTL_DIR_INFO;
FSP_FSCTL_STATIC_ASSERT(104 == sizeof(FSP_FSCTL_DIR_INFO),
"sizeof(FSP_FSCTL_DIR_INFO) must be exactly 104.");
typedef struct
{
UINT16 Size;
UINT64 StreamSize;
UINT64 StreamAllocationSize;
WCHAR StreamNameBuf[];
} FSP_FSCTL_STREAM_INFO;
FSP_FSCTL_STATIC_ASSERT(24 == sizeof(FSP_FSCTL_STREAM_INFO),
"sizeof(FSP_FSCTL_STREAM_INFO) must be exactly 24.");
typedef struct
{
UINT16 Size;
UINT32 Filter;
UINT32 Action;
WCHAR FileNameBuf[];
} FSP_FSCTL_NOTIFY_INFO;
FSP_FSCTL_STATIC_ASSERT(12 == sizeof(FSP_FSCTL_NOTIFY_INFO),
"sizeof(FSP_FSCTL_NOTIFY_INFO) must be exactly 12.");
typedef struct
{
UINT64 UserContext;
UINT64 UserContext2;
} FSP_FSCTL_TRANSACT_FULL_CONTEXT;
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 (PID,HANDLE) */
UINT32 DesiredAccess; /* FILE_{READ_DATA,WRITE_DATA,etc.} */
UINT32 GrantedAccess; /* FILE_{READ_DATA,WRITE_DATA,etc.} */
UINT32 ShareAccess; /* FILE_SHARE_{READ,WRITE,DELETE} */
FSP_FSCTL_TRANSACT_BUF Ea; /* extended attributes or reparse point buffer */
UINT32 UserMode:1; /* request originated in user mode */
UINT32 HasTraversePrivilege:1; /* requestor has TOKEN_HAS_TRAVERSE_PRIVILEGE */
UINT32 HasBackupPrivilege:1; /* requestor has TOKEN_HAS_BACKUP_PRIVILEGE */
UINT32 HasRestorePrivilege:1; /* requestor has TOKEN_HAS_RESTORE_PRIVILEGE */
UINT32 OpenTargetDirectory:1; /* open target dir and report FILE_{EXISTS,DOES_NOT_EXIST} */
UINT32 CaseSensitive:1; /* FileName comparisons should be case-sensitive */
UINT32 HasTrailingBackslash:1; /* FileName had trailing backslash */
UINT32 AcceptsSecurityDescriptor:1;
UINT32 EaIsReparsePoint:1; /* Ea buffer is reparse point */
UINT32 ReservedFlags:24;
UINT16 NamedStream; /* request targets named stream; colon offset in FileName */
} Create;
struct
{
UINT64 UserContext;
UINT64 UserContext2;
UINT32 FileAttributes; /* file attributes for overwritten/superseded files */
UINT64 AllocationSize; /* allocation size for overwritten/superseded files */
UINT32 Supersede:1; /* 0: FILE_OVERWRITE operation, 1: FILE_SUPERSEDE operation */
FSP_FSCTL_TRANSACT_BUF Ea; /* extended attributes buffer */
} Overwrite;
struct
{
UINT64 UserContext;
UINT64 UserContext2;
UINT32 Delete:1; /* file must be deleted */
UINT32 SetAllocationSize:1;
UINT32 SetArchiveBit:1;
UINT32 SetLastAccessTime:1;
UINT32 SetLastWriteTime:1;
UINT32 SetChangeTime:1;
} 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;
UINT64 ChangeTime;
} Basic;
struct
{
UINT32 Delete:1;
} Disposition;
struct
{
UINT32 Flags;
} DispositionEx;
struct
{
UINT64 FileSize;
} EndOfFile;
struct
{
FSP_FSCTL_TRANSACT_BUF NewFileName;
UINT64 AccessToken; /* request access token (PID,HANDLE) */
} Rename;
struct
{
FSP_FSCTL_TRANSACT_BUF NewFileName;
UINT64 AccessToken; /* request access token (PID,HANDLE) */
UINT32 Flags;
} RenameEx;
} Info;
} SetInformation;
struct
{
UINT64 UserContext;
UINT64 UserContext2;
} QueryEa;
struct
{
UINT64 UserContext;
UINT64 UserContext2;
FSP_FSCTL_TRANSACT_BUF Ea;
} SetEa;
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;
UINT32 Length;
FSP_FSCTL_TRANSACT_BUF Pattern;
FSP_FSCTL_TRANSACT_BUF Marker;
UINT32 CaseSensitive:1; /* FileName comparisons should be case-sensitive */
UINT32 PatternIsFileName:1; /* Pattern does not contain wildcards */
} QueryDirectory;
struct
{
UINT64 UserContext;
UINT64 UserContext2;
UINT32 FsControlCode;
FSP_FSCTL_TRANSACT_BUF Buffer;
UINT16 TargetOnFileSystem; /* the target of the symbolic link is on this file system */
} FileSystemControl;
struct
{
UINT64 UserContext;
UINT64 UserContext2;
UINT32 IoControlCode;
FSP_FSCTL_TRANSACT_BUF Buffer;
UINT32 OutputLength;
} DeviceControl;
struct
{
UINT64 UserContext;
UINT64 UserContext2;
} QuerySecurity;
struct
{
UINT64 UserContext;
UINT64 UserContext2;
UINT32 SecurityInformation;
FSP_FSCTL_TRANSACT_BUF SecurityDescriptor;
} SetSecurity;
struct
{
UINT64 UserContext;
UINT64 UserContext2;
} QueryStreamInformation;
} Req;
FSP_FSCTL_TRANSACT_BUF FileName;
/* Create,Cleanup,SetInformation{Disposition,Rename},FileSystemControl{ReparsePoint} */
FSP_FSCTL_DECLSPEC_ALIGN UINT8 Buffer[];
} FSP_FSCTL_TRANSACT_REQ;
typedef struct
{
UINT16 Version;
UINT16 Size;
UINT32 Kind;
UINT64 Hint;
struct
{
UINT32 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_TRANSACT_BUF SecurityDescriptor;
FSP_FSCTL_FILE_INFO FileInfo;
FSP_FSCTL_TRANSACT_BUF FileName;
UINT32 DisableCache:1;
UINT32 HasSecurityDescriptor:1;
} Opened;
/* IoStatus.Status == STATUS_REPARSE */
struct
{
FSP_FSCTL_TRANSACT_BUF Buffer;
} 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_TRANSACT_BUF Ea;
} QueryEa;
struct
{
FSP_FSCTL_FILE_INFO FileInfo;
FSP_FSCTL_TRANSACT_BUF Ea; /* Size==0 means no extended atttributed returned */
} SetEa;
struct
{
FSP_FSCTL_FILE_INFO FileInfo; /* valid when flushing file (not volume) */
} FlushBuffers;
struct
{
FSP_FSCTL_VOLUME_INFO VolumeInfo;
} QueryVolumeInformation;
struct
{
FSP_FSCTL_VOLUME_INFO VolumeInfo;
} SetVolumeInformation;
struct
{
FSP_FSCTL_TRANSACT_BUF Buffer;
} FileSystemControl;
struct
{
FSP_FSCTL_TRANSACT_BUF Buffer;
} DeviceControl;
struct
{
FSP_FSCTL_TRANSACT_BUF SecurityDescriptor;
} QuerySecurity;
struct
{
FSP_FSCTL_TRANSACT_BUF SecurityDescriptor; /* Size==0 means no security descriptor returned */
} SetSecurity;
struct
{
FSP_FSCTL_TRANSACT_BUF Buffer;
} QueryStreamInformation;
} Rsp;
FSP_FSCTL_DECLSPEC_ALIGN UINT8 Buffer[];
} FSP_FSCTL_TRANSACT_RSP;
#pragma warning(pop)
FSP_FSCTL_STATIC_ASSERT(FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMAX > FSP_FSCTL_TRANSACT_PATH_SIZEMAX,
"FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMAX must be greater than FSP_FSCTL_TRANSACT_PATH_SIZEMAX "
"to detect when a normalized name has been set during a Create/Open request.");
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(_KERNEL_MODE)
FSP_API NTSTATUS FspFsctlCreateVolume(PWSTR DevicePath,
const FSP_FSCTL_VOLUME_PARAMS *VolumeParams,
PWCHAR VolumeNameBuf, SIZE_T VolumeNameSize,
PHANDLE PVolumeHandle);
FSP_API NTSTATUS FspFsctlMakeMountdev(HANDLE VolumeHandle,
BOOLEAN Persistent, GUID *UniqueId);
FSP_API NTSTATUS FspFsctlUseMountmgr(HANDLE VolumeHandle,
PWSTR MountPoint);
FSP_API NTSTATUS FspFsctlTransact(HANDLE VolumeHandle,
PVOID ResponseBuf, SIZE_T ResponseBufSize,
PVOID RequestBuf, SIZE_T *PRequestBufSize,
BOOLEAN Batch);
FSP_API NTSTATUS FspFsctlStop(HANDLE VolumeHandle);
FSP_API NTSTATUS FspFsctlStop0(HANDLE VolumeHandle);
FSP_API NTSTATUS FspFsctlNotify(HANDLE VolumeHandle,
FSP_FSCTL_NOTIFY_INFO *NotifyInfo, SIZE_T Size);
FSP_API NTSTATUS FspFsctlGetVolumeList(PWSTR DevicePath,
PWCHAR VolumeListBuf, PSIZE_T PVolumeListSize);
FSP_API NTSTATUS FspFsctlPreflight(PWSTR DevicePath);
FSP_API NTSTATUS FspFsctlServiceVersion(PUINT32 PVersion);
FSP_API NTSTATUS FspFsctlStartService(VOID);
FSP_API NTSTATUS FspFsctlStopService(VOID);
FSP_API NTSTATUS FspFsctlEnumServices(
VOID (*EnumFn)(PVOID Context, PWSTR ServiceName, BOOLEAN Running),
PVOID Context);
typedef struct
{
/* in */
HANDLE VolumeHandle; /* volume handle returned by FspFsctlCreateVolume */
PWSTR VolumeName; /* volume name returned by FspFsctlCreateVolume */
PSECURITY_DESCRIPTOR Security; /* optional: security descriptor for directories */
UINT64 Reserved; /* reserved for future use */
/* in/out */
PWSTR MountPoint; /* FspMountSet sets drive in buffer when passed "*:" */
HANDLE MountHandle; /* FspMountSet sets, FspMountRemove uses */
} FSP_MOUNT_DESC;
FSP_API NTSTATUS FspMountSet(FSP_MOUNT_DESC *Desc);
FSP_API NTSTATUS FspMountRemove(FSP_MOUNT_DESC *Desc);
#endif
/*
* Atomics
*
* See https://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html (https://archive.is/mJfFX)
*/
#if _MSC_VER >= 1920 /* VS2019 or later */
__int32 __iso_volatile_load32(const volatile __int32 *);
void __iso_volatile_store32(volatile __int32 *, __int32);
__int64 __iso_volatile_load64(const volatile __int64 *);
void __iso_volatile_store64(volatile __int64 *, __int64);
#define FSP_INTERLOCKED__LOAD32(p) __iso_volatile_load32(p)
#define FSP_INTERLOCKED__STORE32(p,v) __iso_volatile_store32(p,v)
#define FSP_INTERLOCKED__LOAD64(p) __iso_volatile_load64(p)
#define FSP_INTERLOCKED__STORE64(p,v) __iso_volatile_store64(p,v)
#else
#define FSP_INTERLOCKED__LOAD32(p) (*(p))
#define FSP_INTERLOCKED__STORE32(p,v) (*(p) = (v))
#define FSP_INTERLOCKED__LOAD64(p) (*(p))
#define FSP_INTERLOCKED__STORE64(p,v) (*(p) = (v))
#endif
static inline INT32 FspInterlockedLoad32(INT32 volatile *p)
{
#if defined(_M_ARM64)
void __dmb(unsigned int);
INT32 v = FSP_INTERLOCKED__LOAD32(p);
__dmb(0xb);
return v;
#elif defined(_M_X64) || defined(_M_IX86)
void _ReadWriteBarrier(void);
INT32 v = FSP_INTERLOCKED__LOAD32(p);
_ReadWriteBarrier();
return v;
#endif
}
static inline VOID FspInterlockedStore32(INT32 volatile *p, INT32 v)
{
#if defined(_M_ARM64)
void __dmb(unsigned int);
__dmb(0xb);
FSP_INTERLOCKED__STORE32(p, v);
__dmb(0xb);
#elif defined(_M_X64) || defined(_M_IX86)
long _InterlockedExchange(long volatile *, long);
_InterlockedExchange((long volatile *)p, v);
#endif
}
static inline VOID *FspInterlockedLoadPointer(VOID *volatile *p)
{
#if defined(_M_ARM64)
void __dmb(unsigned int);
VOID *v = (VOID *)FSP_INTERLOCKED__LOAD64((__int64 volatile *)(p));
__dmb(0xb);
return v;
#elif defined(_M_X64)
void _ReadWriteBarrier(void);
VOID *v = (VOID *)FSP_INTERLOCKED__LOAD64((__int64 volatile *)(p));
_ReadWriteBarrier();
return v;
#elif defined(_M_IX86)
void _ReadWriteBarrier(void);
VOID *v = (VOID *)FSP_INTERLOCKED__LOAD32((__int32 volatile *)(p));
_ReadWriteBarrier();
return v;
#endif
}
static inline VOID FspInterlockedStorePointer(VOID *volatile *p, VOID *v)
{
#if defined(_M_ARM64)
void __dmb(unsigned int);
__dmb(0xb);
FSP_INTERLOCKED__STORE64((__int64 volatile *)(p), (__int64)(v));
__dmb(0xb);
#elif defined(_M_X64) || defined(_M_IX86)
void *_InterlockedExchangePointer(void *volatile *, void *);
_InterlockedExchangePointer(p, v);
#endif
}
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,350 @@
/**
* @file winfsp/launch.h
* WinFsp Launch API.
*
* In order to use the WinFsp Launch API a program must include &lt;winfsp/launch.h&gt;
* and link with the winfsp_x64.dll (or winfsp_x86.dll) library.
*
* @copyright 2015-2025 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
*
* You can redistribute it and/or modify it under the terms of the GNU
* General Public License version 3 as published by the Free Software
* Foundation.
*
* Licensees holding a valid commercial license may use this software
* in accordance with the commercial license agreement provided in
* conjunction with the software. The terms and conditions of any such
* commercial license agreement shall govern, supersede, and render
* ineffective any application of the GPLv3 license to this software,
* notwithstanding of any reference thereto in the software or
* associated repository.
*/
#ifndef WINFSP_LAUNCH_H_INCLUDED
#define WINFSP_LAUNCH_H_INCLUDED
#include <winfsp/winfsp.h>
#ifdef __cplusplus
extern "C" {
#endif
#define FSP_LAUNCH_REGKEY FSP_FSCTL_PRODUCT_REGKEY "\\Services"
#define FSP_LAUNCH_REGKEY_WOW64 FSP_FSCTL_PRODUCT_REGKEY_WOW64
#define FSP_LAUNCH_FULL_REGKEY FSP_FSCTL_PRODUCT_FULL_REGKEY "\\Services"
#define FSP_LAUNCH_PIPE_NAME "\\\\.\\pipe\\" FSP_FSCTL_PRODUCT_NAME ".{14E7137D-22B4-437A-B0C1-D21D1BDF3767}"
#define FSP_LAUNCH_PIPE_BUFFER_SIZE 4096
#define FSP_LAUNCH_PIPE_OWNER ((PSID)WinLocalSystemSid)
/*
* The launcher named pipe SDDL gives full access to LocalSystem and Administrators and
* GENERIC_READ and FILE_WRITE_DATA access to Everyone. We are careful not to give the
* FILE_CREATE_PIPE_INSTANCE right to Everyone to disallow the creation of additional
* pipe instances.
*/
#define FSP_LAUNCH_PIPE_SDDL "O:SYG:SYD:P(A;;GA;;;SY)(A;;GA;;;BA)(A;;GRDCCR;;;WD)"
/*
* The default service instance SDDL gives full access to LocalSystem and Administrators.
* The only possible service instance rights are as follows:
* RP SERVICE_START
* WP SERVICE_STOP
* LC SERVICE_QUERY_STATUS
*
* To create a service that can be started, stopped or queried by Everyone, you can set
* the following SDDL:
* D:P(A;;RPWPLC;;;WD)
*/
#define FSP_LAUNCH_SERVICE_DEFAULT_SDDL "D:P(A;;RPWPLC;;;SY)(A;;RPWPLC;;;BA)"
#define FSP_LAUNCH_SERVICE_WORLD_SDDL "D:P(A;;RPWPLC;;;WD)"
enum
{
FspLaunchCmdStart = 'S', /* requires: SERVICE_START */
FspLaunchCmdStartWithSecret = 'X', /* requires: SERVICE_START */
FspLaunchCmdStop = 'T', /* requires: SERVICE_STOP */
FspLaunchCmdGetInfo = 'I', /* requires: SERVICE_QUERY_STATUS */
FspLaunchCmdGetNameList = 'L', /* requires: none*/
FspLaunchCmdDefineDosDevice = 'D', /* internal: do not use! */
FspLaunchCmdQuit = 'Q', /* DEBUG version only */
};
enum
{
FspLaunchCmdSuccess = '$',
FspLaunchCmdFailure = '!',
};
/**
* @group Launch Control
*/
/**
* Call launcher pipe.
*
* This function is used to send a command to the launcher and receive a response.
*
* @param Command
* Launcher command to send. For example, the 'L' launcher command instructs
* the launcher to list all running service instances.
* @param Argc
* Command argument count. May be 0.
* @param Argv
* Command argument array. May be NULL.
* @param Argl
* Command argument length array. May be NULL. If this is NULL all command arguments
* are assumed to be NULL-terminated strings. It is also possible for specific arguments
* to be NULL-terminated; in this case pass -1 in the corresponding Argl position.
* @param Buffer
* Buffer that receives the command response. May be NULL.
* @param PSize
* Pointer to a ULONG. On input it contains the size of the Buffer. On output it
* contains the number of bytes transferred. May be NULL.
* @param PLauncherError
* Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
* @return
* STATUS_SUCCESS if the command is sent successfully to the launcher, even if the launcher
* returns an error. Other status codes indicate a communication error. Launcher errors are
* reported through PLauncherError.
*/
FSP_API NTSTATUS FspLaunchCallLauncherPipe(
WCHAR Command, ULONG Argc, PWSTR *Argv, ULONG *Argl,
PWSTR Buffer, PULONG PSize,
PULONG PLauncherError);
/**
* Call launcher pipe.
*
* This function is used to send a command to the launcher and receive a response.
*
* @param Command
* Launcher command to send. For example, the 'L' launcher command instructs
* the launcher to list all running service instances.
* @param Argc
* Command argument count. May be 0.
* @param Argv
* Command argument array. May be NULL.
* @param Argl
* Command argument length array. May be NULL. If this is NULL all command arguments
* are assumed to be NULL-terminated strings. It is also possible for specific arguments
* to be NULL-terminated; in this case pass -1 in the corresponding Argl position.
* @param Buffer
* Buffer that receives the command response. May be NULL.
* @param PSize
* Pointer to a ULONG. On input it contains the size of the Buffer. On output it
* contains the number of bytes transferred. May be NULL.
* @param AllowImpersonation
* Allow caller to be impersonated by launcher.
* @param PLauncherError
* Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
* @return
* STATUS_SUCCESS if the command is sent successfully to the launcher, even if the launcher
* returns an error. Other status codes indicate a communication error. Launcher errors are
* reported through PLauncherError.
*/
FSP_API NTSTATUS FspLaunchCallLauncherPipeEx(
WCHAR Command, ULONG Argc, PWSTR *Argv, ULONG *Argl,
PWSTR Buffer, PULONG PSize,
BOOLEAN AllowImpersonation,
PULONG PLauncherError);
/**
* Start a service instance.
*
* @param ClassName
* Class name of the service instance to start.
* @param InstanceName
* Instance name of the service instance to start.
* @param Argc
* Service instance argument count. May be 0.
* @param Argv
* Service instance argument array. May be NULL.
* @param HasSecret
* Whether the last argument in Argv is assumed to be a secret (e.g. password) or not.
* Secrets are passed to service instances through standard input rather than the command
* line.
* @param PLauncherError
* Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
* @return
* STATUS_SUCCESS if the command is sent successfully to the launcher, even if the launcher
* returns an error. Other status codes indicate a communication error. Launcher errors are
* reported through PLauncherError.
*/
FSP_API NTSTATUS FspLaunchStart(
PWSTR ClassName, PWSTR InstanceName, ULONG Argc, PWSTR *Argv,
BOOLEAN HasSecret,
PULONG PLauncherError);
/**
* Start a service instance.
*
* @param ClassName
* Class name of the service instance to start.
* @param InstanceName
* Instance name of the service instance to start.
* @param Argc
* Service instance argument count. May be 0.
* @param Argv
* Service instance argument array. May be NULL.
* @param HasSecret
* Whether the last argument in Argv is assumed to be a secret (e.g. password) or not.
* Secrets are passed to service instances through standard input rather than the command
* line.
* @param AllowImpersonation
* Allow caller to be impersonated by launcher.
* @param PLauncherError
* Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
* @return
* STATUS_SUCCESS if the command is sent successfully to the launcher, even if the launcher
* returns an error. Other status codes indicate a communication error. Launcher errors are
* reported through PLauncherError.
*/
FSP_API NTSTATUS FspLaunchStartEx(
PWSTR ClassName, PWSTR InstanceName, ULONG Argc, PWSTR *Argv,
BOOLEAN HasSecret,
BOOLEAN AllowImpersonation,
PULONG PLauncherError);
/**
* Stop a service instance.
*
* @param ClassName
* Class name of the service instance to stop.
* @param InstanceName
* Instance name of the service instance to stop.
* @param PLauncherError
* Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
* @return
* STATUS_SUCCESS if the command is sent successfully to the launcher, even if the launcher
* returns an error. Other status codes indicate a communication error. Launcher errors are
* reported through PLauncherError.
*/
FSP_API NTSTATUS FspLaunchStop(
PWSTR ClassName, PWSTR InstanceName,
PULONG PLauncherError);
/**
* Get information about a service instance.
*
* The information is a list of NULL-terminated strings: the class name of the service instance,
* the instance name of the service instance and the full command line used to start the service
* instance.
*
* @param ClassName
* Class name of the service instance to stop.
* @param InstanceName
* Instance name of the service instance to stop.
* @param Buffer
* Buffer that receives the command response. May be NULL.
* @param PSize
* Pointer to a ULONG. On input it contains the size of the Buffer. On output it
* contains the number of bytes transferred. May be NULL.
* @param PLauncherError
* Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
* @return
* STATUS_SUCCESS if the command is sent successfully to the launcher, even if the launcher
* returns an error. Other status codes indicate a communication error. Launcher errors are
* reported through PLauncherError.
*/
FSP_API NTSTATUS FspLaunchGetInfo(
PWSTR ClassName, PWSTR InstanceName,
PWSTR Buffer, PULONG PSize,
PULONG PLauncherError);
/**
* List service instances.
*
* The information is a list of pairs of NULL-terminated strings. Each pair contains the class
* name and instance name of a service instance. All currently running service instances are
* listed.
*
* @param Buffer
* Buffer that receives the command response. May be NULL.
* @param PSize
* Pointer to a ULONG. On input it contains the size of the Buffer. On output it
* contains the number of bytes transferred. May be NULL.
* @param PLauncherError
* Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
* @return
* STATUS_SUCCESS if the command is sent successfully to the launcher, even if the launcher
* returns an error. Other status codes indicate a communication error. Launcher errors are
* reported through PLauncherError.
*/
FSP_API NTSTATUS FspLaunchGetNameList(
PWSTR Buffer, PULONG PSize,
PULONG PLauncherError);
/**
* @group Service Registry
*/
#pragma warning(push)
#pragma warning(disable:4200) /* zero-sized array in struct/union */
/**
* Service registry record.
*/
typedef struct _FSP_LAUNCH_REG_RECORD
{
PWSTR Agent;
PWSTR Executable;
PWSTR CommandLine;
PWSTR WorkDirectory;
PWSTR RunAs;
PWSTR Security;
PWSTR AuthPackage;
PWSTR Stderr;
PVOID Reserved0[4];
ULONG JobControl;
ULONG Credentials;
ULONG AuthPackageId;
ULONG Recovery;
ULONG Reserved1[4];
UINT8 Buffer[];
} FSP_LAUNCH_REG_RECORD;
#pragma warning(pop)
/**
* Add/change/delete a service registry record.
*
* @param ClassName
* The service class name.
* @param Record
* The record to set in the registry. If NULL, the registry record is deleted.
* @return
* STATUS_SUCCESS or error code.
*/
FSP_API NTSTATUS FspLaunchRegSetRecord(
PWSTR ClassName,
const FSP_LAUNCH_REG_RECORD *Record);
/**
* Get a service registry record.
*
* @param ClassName
* The service class name.
* @param Agent
* The name of the agent that is retrieving the service record. This API matches
* the supplied Agent against the Agent in the service record and it only returns
* the record if they match. Pass NULL to match any Agent.
* @param PRecord
* Pointer to a record pointer. Memory for the service record will be allocated
* and a pointer to it will be stored at this address. This memory must be later
* freed using FspLaunchRegFreeRecord.
* @return
* STATUS_SUCCESS or error code.
* @see
* FspLaunchRegFreeRecord
*/
FSP_API NTSTATUS FspLaunchRegGetRecord(
PWSTR ClassName, PWSTR Agent,
FSP_LAUNCH_REG_RECORD **PRecord);
/**
* Free a service registry record.
*
* @param Record
* The service record to free.
* @see
* FspLaunchRegGetRecord
*/
FSP_API VOID FspLaunchRegFreeRecord(
FSP_LAUNCH_REG_RECORD *Record);
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff