Dokan Library
Dokan Library, commonly referred to as Dokany in its modern iteration, is an open-source user-mode file system library for Microsoft Windows that allows developers to create virtual file systems without writing kernel-level drivers, providing a safer and more accessible alternative to traditional low-level file system development.[1]
Originally developed by Hiroki Asakawa between 2007 and 2011 as a Windows equivalent to the Linux FUSE (Filesystem in Userspace) framework, Dokan enables the mounting of arbitrary data sources—such as archives, cloud storage, or in-memory structures—as fully functional drives accessible to standard Windows applications.[1] After Asakawa's initial work, the project entered a community-maintenance phase from 2011 to 2014 before being revived and actively maintained since 2014 by developers Adrien J. and Maxime C., with ongoing support from the company ISLOG and a growing open-source contributor base.[1][2]
Key features of Dokan include a user-mode API supporting multiple programming languages such as C, .NET, Java, Delphi, and Ruby for operations like mounting and unmounting file systems, as well as a FUSE compatibility wrapper that facilitates porting of Linux-based file system code to Windows.[1] It incorporates access control mechanisms through custom security descriptors and emphasizes safety by avoiding kernel-mode interactions, thereby preventing common issues like system crashes (blue screens of death) during development and testing.[1] The library has been instrumental in various applications, including file synchronization tools like Keybase, virtual drive implementations such as Nodrive, and cloud-based file systems like DokanCloudFS, demonstrating its versatility in bridging user-space logic with Windows' file system architecture.[1] Dokany receives updates, with releases up to 2023 focusing on bug fixes, memory leak resolutions, and enhanced parameter handling to improve stability and performance. The latest stable release is version 2.3.1 (September 2023), distributed under the MIT and LGPL licenses.[3][1]
Overview
Purpose and Functionality
The Dokan Library is a user-mode file system library for Windows that enables developers to implement virtual file systems without the need for kernel-level drivers.[1] It serves as a bridge between user-space applications and the Windows file system, allowing custom file system behaviors to be exposed through standard operating system interfaces.[2]
Its primary functionality involves mounting virtual storage—such as in-memory data structures, archived files, or remote resources accessed via protocols like FTP or SSH—as local drives that appear natively in Windows Explorer and are accessible via conventional APIs like Win32 or .NET.[1] Developers can define how these virtual files and directories behave by implementing callback functions for core operations, including creating, reading, writing, and deleting files, which Dokan then translates into a cohesive, user-visible file system.[4] This approach mirrors the user-mode file system paradigm of FUSE on Linux but is tailored for the Windows environment.[5]
By operating entirely in user mode, Dokan simplifies file system development by sidestepping the complexities and stability requirements of kernel-mode programming, thereby reducing the risk of system crashes like Blue Screen of Death (BSOD) and facilitating easier debugging and testing.[1] It also supports layered security models, enabling fine-grained access controls without compromising the overall system integrity.[2] These benefits make Dokan particularly valuable for rapid prototyping of custom storage solutions, such as virtual disks for cloud synchronization or encrypted containers, while maintaining compatibility with existing Windows applications.[1]
Key Features
Dokan Library provides several mount options that enhance its flexibility for virtual file system deployment. Users can configure a file system as read-only using the DOKAN_OPTION_MOUNT_READONLY flag, which prevents write operations and ensures data integrity in scenarios like archival or distribution systems.[6] To simulate removable media, the DOKAN_OPTION_REMOVABLE option allows the virtual drive to behave like a USB device, supporting ejection notifications and media removal events. Additionally, network drive emulation is enabled via DOKAN_OPTION_NETWORK, integrating the virtual file system into Windows Explorer as a remote share, complete with support for the Dokan Network Provider for UNC path access.[6]
The library employs a multi-threaded operation model by default, enabling efficient handling of concurrent file I/O requests from multiple processes or threads. This design requires callback functions in the DOKAN_OPERATIONS structure to be thread-safe, allowing high-throughput access without the need for explicit synchronization in simple implementations; however, the SingleThread option can be specified for sequential processing if concurrency is not required.[6] Such parallelism contributes to the library's suitability for performance-sensitive applications while maintaining user-mode safety.
Security features in Dokan Library align closely with native Windows mechanisms, including support for access control lists (ACLs) and security descriptors. Through the DOKAN_OPERATIONS callbacks, such as GetFileSecurity and SetFileSecurity, developers can implement permission checks that mimic NTFS semantics, enforcing user and group-based access rights on virtual files and directories.[6]
Performance optimizations are facilitated by built-in caching mechanisms for file metadata and data. The DOKAN_FILE_INFO.Context field allows per-file caching of state information across operations, reducing redundant computations and I/O overhead during repeated accesses within the same session.[6] This approach minimizes latency in virtual file systems handling large datasets or frequent queries.
Error handling in Dokan Library adheres to standardized Windows NT status codes for compatibility with the operating system's native error reporting. Functions return codes like STATUS_SUCCESS for successful operations or STATUS_OBJECT_NAME_NOT_FOUND for missing files, with utilities such as DokanNtStatusFromWin32 enabling seamless conversion from Win32 error values to NTSTATUS equivalents.[6] This ensures consistent behavior and debugging across Windows applications interacting with Dokan-mounted drives.
History
Original Development
The Dokan Library was created by Japanese developer Hiroki Asakawa in 2007 as an open-source project to enable user-mode file system development on Windows.[1] The initial release was hosted on Google Code, where it provided a framework similar to FUSE on Linux, allowing programmers to implement virtual file systems without writing low-level kernel drivers.[7]
Asakawa's primary goal was to democratize file system creation by simplifying the process for Windows developers, who previously faced significant barriers due to the platform's kernel-mode requirements for such functionality.[1] This approach emphasized ease of use and safety, positioning Dokan as a tool for rapid prototyping and experimentation in storage solutions.[7]
Active development spanned from 2007 to 2011, during which Asakawa released several iterations building core features like file operations and mount management.[1] The project culminated in version 0.6.0 in 2011, the final official release under Asakawa's maintenance, after which community forks took over to continue its evolution.[1]
Forks and Maintenance
Following the original development of Dokan Library by Hiroki Asakawa, which concluded around version 0.6.0 in 2011, community efforts led to the emergence of forks to address ongoing bugs and maintenance needs.[1]
One early fork, DokanX, was initiated around 2013 by community contributor Benjamin Kim to improve stability and compatibility in versions prior to 0.6.0, incorporating updates like Visual Studio 2013 support and enhanced logging.[8] However, development on DokanX slowed significantly after 2014, with the last commit occurring approximately 10 years prior to 2025, rendering it largely inactive by that time.[8]
In 2014, as community forks like DokanX waned, the French company ISLOG launched the Dokany fork based on Dokan 0.6.0, emphasizing bug fixes, a clean commit history, and compatibility with modern build tools.[1] This fork, now hosted under the dokan-dev organization, has been actively maintained by key contributors including Adrien Jund, with support from ISLOG for code signing and resources.[1] Dokany's development shifted to GitHub in 2014, fostering community involvement through issues, pull requests, and a comprehensive wiki for documentation and migration guides.[2][4]
Major maintenance milestones in Dokany include API changes in version 0.8.0 (released in 2016), which broke compatibility with prior Dokan APIs to enable cleaner enhancements; version 1.1.0 (2018), introducing further refinements documented in update guides; and version 2.0.0 (2020), with additional API adjustments for improved functionality.[9][10][2] The project continues to evolve, with the latest release, 2.3.1.1000, issued on September 28, 2025, featuring signed drivers for enhanced security and deployment ease.
To promote broader adoption, Dokany transitioned to a dual licensing model under the GNU Lesser General Public License (LGPL) for core components like the user-mode library and kernel driver, alongside the MIT License for utilities such as the control program and sample code.[11] This shift, implemented since the early fork stages, has supported ongoing community contributions and integration into diverse projects while maintaining open-source accessibility.[1]
Architecture
Components and Operation
The Dokan Library operates through a dual-component architecture consisting of a user-mode dynamic-link library (dokan2.dll) and a kernel-mode file system driver (dokan2.sys). The user-mode DLL provides the interface for developers to implement file system logic by registering callback functions, allowing safe execution in user space without direct kernel modifications. Meanwhile, the kernel-mode driver intercepts file input/output (I/O) operations from the Windows kernel, simulating a virtual file system by proxying requests to the user-mode application.[2][6]
In the operation flow, a mount request from the user-mode application loads the dokan2.sys driver if not already active. When a user program issues a file operation—such as opening a file via CreateFile—the Windows I/O manager generates an I/O Request Packet (IRP), such as IRP_MJ_CREATE, which the driver intercepts and forwards as a callback to the user-mode DLL. The DLL then invokes the developer's registered callback function, equivalent to Windows Native API calls like ZwCreateFile, passing context via a DOKAN_FILE_INFO structure. This callback processes the request and returns a status (e.g., STATUS_SUCCESS or STATUS_OBJECT_NAME_NOT_FOUND), which the driver relays back to the kernel to complete the operation. The model supports asynchronous handling, as the driver queues IRPs and invokes callbacks in a thread-safe manner, ensuring sequential processing from creation to cleanup and close events.[6][2]
The mount process begins with the user-mode application specifying a MountPoint—such as a drive letter (e.g., "Z:") or folder path—and configuring options via the DOKAN_OPTIONS structure, which defines behaviors like threading mode or debug output. The DokanMain or DokanCreateFileSystem function initializes the file system, integrating it into the Windows namespace by loading the driver and associating the mount point. DokanMain blocks until unmount and returns an int status; DokanCreateFileSystem (introduced in Dokany 2.0) is asynchronous and outputs a DOKAN_HANDLE for control. For unmounting and cleanup, DokanRemoveMountPoint detaches the file system, ceasing callback invocations, while DokanCloseHandle (for handles from DokanCreateFileSystem) ensures proper resource release, preventing lingering kernel handles.[6][2]
API Structure
The Dokan Library provides a C-based API for implementing user-mode file systems on Windows, primarily through two core structures: DOKAN_OPTIONS and DOKAN_OPERATIONS. The DOKAN_OPTIONS structure configures the mounting behavior of the virtual file system, including fields such as Version (a USHORT specifying the Dokan features version, e.g., 200 for version 2.0.0), SingleThread (a BOOLEAN to enable single-threaded event processing, though multi-threading is recommended for performance), Options (an ULONG bitmask for features like DOKAN_OPTION_CASE_SENSITIVE for case-sensitive path handling or DOKAN_OPTION_NETWORK for UNC provider emulation), MountPoint (LPCWSTR for the drive letter or path, e.g., "Z:"), Timeout (ULONG in milliseconds for request timeouts, defaulting to 15000), and AllocationUnitSize/SectorSize (ULONGS influencing reported volume geometry).[12] Additional fields like UNCName (LPCWSTR for network redirector support) and VolumeSecurityDescriptor (a security descriptor buffer for volume ACLs) allow customization of access controls and network visibility.[12]
The DOKAN_OPERATIONS structure serves as a table of function pointers for handling file system events, enabling developers to implement callbacks for operations like file creation, reading, and directory enumeration. Critical callbacks include ZwCreateFile (for opening or creating files/directories, taking parameters such as FileName as LPCWSTR, DesiredAccess as ACCESS_MASK, CreateDisposition as ULONG, and DokanFileInfo for context), ReadFile (for reading data, with Buffer as LPVOID, BufferLength as DWORD, ReadLength as LPDWORD, Offset as LONGLONG, and DokanFileInfo), and WriteFile (for writing data, using Buffer, NumberOfBytesToWrite as DWORD, NumberOfBytesWritten as LPDWORD, Offset as LONGLONG, and DokanFileInfo).[13] Other essential operations encompass FindFiles (for directory listing via FillFindData callback), GetFileInformation (retrieving BY_HANDLE_FILE_INFORMATION via Buffer), FlushFileBuffers (ensuring data persistence), and CloseFile (for cleanup). Unimplemented callbacks can return STATUS_NOT_IMPLEMENTED, but core ones like read/write must be provided to avoid instability.[13]
Key top-level functions manage the file system's lifecycle, with DokanMain initiating the mount by passing DOKAN_OPTIONS and DOKAN_OPERATIONS instances and blocking until unmount, returning an int status (DokanMainResult). The asynchronous DokanCreateFileSystem (in Dokany 2.0+) outputs a DOKAN_HANDLE for further control, such as notifications.[14] Unmounting is handled by DokanRemoveMountPoint, which detaches the device from a specified path or drive letter (e.g., "Z:"), returning TRUE on success.[14] Initialization requires a prior call to DokanInit (once per process) and cleanup via DokanShutdown. All operation callbacks return NTSTATUS codes for error handling, such as STATUS_SUCCESS (0x00000000L) for successful operations or STATUS_ACCESS_DENIED (0xC0000022L) for permission issues, convertible from Win32 errors using DokanNtStatusFromWin32.[14]
Version-specific enhancements include the addition of security-related callbacks in Dokany 0.6.0, such as GetFileSecurity (retrieving descriptors via SecurityInformation as SECURITY_INFORMATION, SecurityDescriptor as PSECURITY_DESCRIPTOR, and BufferLength/LengthNeeded as PDWORD) and SetFileSecurity (applying descriptors similarly), enabling fine-grained ACL management.[13] Later versions like Dokany 2.0.0 introduced asynchronous mounting options with DokanCreateFileSystem, while requiring DokanInit for resource management.[10] These evolutions maintain backward compatibility where possible but emphasize modern NTSTATUS-based error propagation for robust integration with Windows APIs.[10]
Operating Systems
The Dokan Library, through its modern iteration known as Dokany, provides client support for Windows 7 SP1, Windows 8, Windows 8.1, Windows 10, and Windows 11 across all editions.[2] Server support extends to Windows Server 2008 R2 SP1, Windows Server 2012, Windows Server 2012 R2, Windows Server 2016, Windows Server 2019, and Windows Server 2022.[2]
Current versions require Windows 7 SP1 or newer for full compatibility; older versions (pre-0.8.0) provided basic functionality on Windows Vista, but are no longer maintained. Installation of the Dokan kernel driver necessitates administrative privileges to ensure proper system integration and security.[15]
Version-specific behaviors include enhanced User Account Control (UAC) compatibility starting with Windows 10, which improves handling of elevated privileges for file system operations without frequent prompts.[15] ARM64 architecture support was added in later versions, with binaries available since at least 2021, enabling deployment on Windows 10 and later for embedded applications.[2][16]
Although Windows 7 reached end-of-life in 2020, Dokany continues to list it as supported as of the latest release (version 2.3.1.1000, September 2023), but users may face unpatched vulnerabilities in the underlying OS.[2][3]
Hardware Architectures
The Dokan Library, particularly in its actively maintained Dokany fork, supports the x86 (32-bit), x64 (64-bit), ARM, and ARM64 processor architectures, enabling compatibility with standard Windows desktop, server, and ARM-based environments.[2] These architectures support the library's user-mode file system operations on Intel, AMD, and Qualcomm processors.[17]
Support for ARM and ARM64 architectures was added in later versions, with official binaries available starting around 2021, extending compatibility to Windows 10 and later on ARM-based devices.[3][16] This allows developers to implement virtual file systems on mobile and edge computing hardware, though adoption remains limited compared to x86/x64.[16]
Build configurations for Dokan Library accommodate cross-compilation via MinGW (using MSYS2 toolchains) and Cygwin environments, facilitating development across architectures without native hardware.[17] Native builds require Visual Studio 2019 or later, along with Windows SDK and Windows Driver Kit (WDK) version 10, ensuring compatibility with modern Windows toolchains for all supported processors.[17]
Binary distributions include digitally signed release and debug drivers for x64 and ARM64 architectures, available through official releases to meet Windows security standards.[3] Dokany provides ongoing support for 32-bit x86 in its builds.[2]
The library lacks specific optimizations for GPU acceleration or embedded systems, focusing instead on general-purpose CPU-based file system emulation.[2] Driver signing is mandatory for 64-bit Windows installations since the policy enforcement in Windows 10 version 1607 (Anniversary Update) in 2016, requiring Extended Validation (EV) certificates or Microsoft Hardware Lab submission for non-test mode deployment.[18]
Applications
End-User Applications
Dokan Library powers a range of end-user software that simplifies file management tasks by creating virtual file systems accessible through familiar Windows interfaces, without requiring users to write code or manage kernel drivers.
In data recovery tools, Disk Drill integrates Dokan to generate virtual previews of files salvaged from damaged or formatted drives, allowing users to browse recoverable data in a standard folder view and select items for restoration while avoiding writes to the original storage.[19]
Cloud storage mounting benefits from Dokan in open-source applications like DokanCloudFS, which extends this capability to additional providers including OneDrive and MEGA, offering end-users a virtual drive for seamless cloud integration.[1]
Virtualization aids powered by Dokan include ramdisk creators that allocate in-memory drives for accelerated temporary file operations, such as caching or testing environments; prototypes like Dokan.Mem illustrate this by implementing a fully functional RAM-based file system accessible as a standard drive.[20]
End-users encounter Dokan primarily through bundled installations in these applications, where the library's drivers are automatically set up during software setup, ensuring compatibility and ease of use without manual configuration.[1]
Developer Applications
Developers utilize the Dokan Library to implement custom file systems by defining callback functions that handle file operations, enabling scenarios such as virtual drives, remote storage integration, and secure data access without kernel-mode development.[2]
A simple mirror file system serves as an introductory example, where operations on a virtual drive are redirected to an existing local directory. In this implementation, the ReadFile and WriteFile callbacks open the corresponding file in the source directory and forward the I/O requests. For instance, the ReadFile function constructs the full path to the source file, opens it if necessary, and uses Windows' ReadFile API with an OVERLAPPED structure to read the specified buffer at the given offset, returning the number of bytes read. Similarly, WriteFile handles writing by adjusting for paging I/O and file size limits, ensuring writes append or overwrite correctly in the source. The following code snippets from the official mirror sample illustrate this redirection:
c
static NTSTATUS DOKAN_CALLBACK MirrorReadFile(
LPCWSTR FileName, LPVOID Buffer, DWORD BufferLength,
LPDWORD ReadLength, LONGLONG Offset, PDOKAN_FILE_INFO DokanFileInfo) {
// Path construction and handle management
WCHAR filePath[DOKAN_MAX_PATH];
HANDLE handle = (HANDLE)DokanFileInfo->Context;
// ... (open file if needed)
OVERLAPPED overlap = {0};
overlap.Offset = Offset & 0xFFFFFFFF;
overlap.OffsetHigh = (Offset >> 32) & 0xFFFFFFFF;
if (!ReadFile(handle, Buffer, BufferLength, ReadLength, &overlap)) {
// Error handling
return DokanNtStatusFromWin32(GetLastError());
}
// Close if opened
return STATUS_SUCCESS;
}
static NTSTATUS DOKAN_CALLBACK MirrorReadFile(
LPCWSTR FileName, LPVOID Buffer, DWORD BufferLength,
LPDWORD ReadLength, LONGLONG Offset, PDOKAN_FILE_INFO DokanFileInfo) {
// Path construction and handle management
WCHAR filePath[DOKAN_MAX_PATH];
HANDLE handle = (HANDLE)DokanFileInfo->Context;
// ... (open file if needed)
OVERLAPPED overlap = {0};
overlap.Offset = Offset & 0xFFFFFFFF;
overlap.OffsetHigh = (Offset >> 32) & 0xFFFFFFFF;
if (!ReadFile(handle, Buffer, BufferLength, ReadLength, &overlap)) {
// Error handling
return DokanNtStatusFromWin32(GetLastError());
}
// Close if opened
return STATUS_SUCCESS;
}
c
static NTSTATUS DOKAN_CALLBACK MirrorWriteFile(
LPCWSTR FileName, LPCVOID Buffer, DWORD NumberOfBytesToWrite,
LPDWORD NumberOfBytesWritten, LONGLONG Offset, PDOKAN_FILE_INFO DokanFileInfo) {
// Similar path and handle setup
// File size check and adjustment for PagingIo
OVERLAPPED overlap = {0};
// Set offset or end-of-file
if (!WriteFile(handle, Buffer, NumberOfBytesToWrite, NumberOfBytesWritten, &overlap)) {
// Error handling
return DokanNtStatusFromWin32(GetLastError());
}
return STATUS_SUCCESS;
}
static NTSTATUS DOKAN_CALLBACK MirrorWriteFile(
LPCWSTR FileName, LPCVOID Buffer, DWORD NumberOfBytesToWrite,
LPDWORD NumberOfBytesWritten, LONGLONG Offset, PDOKAN_FILE_INFO DokanFileInfo) {
// Similar path and handle setup
// File size check and adjustment for PagingIo
OVERLAPPED overlap = {0};
// Set offset or end-of-file
if (!WriteFile(handle, Buffer, NumberOfBytesToWrite, NumberOfBytesWritten, &overlap)) {
// Error handling
return DokanNtStatusFromWin32(GetLastError());
}
return STATUS_SUCCESS;
}
This approach mirrors the source directory transparently, with the virtual drive mounted via DokanMain using options like DOKAN_OPTION_NETWORK for network-like behavior.[21]
For advanced applications, developers implement encrypted virtual drives by customizing callbacks to perform on-the-fly encryption and decryption. In projects like cppcryptfs, which ports the gocryptfs overlay filesystem to Windows, the CreateFile callback decrypts encrypted filenames and file contents during access, presenting an unencrypted view to applications while storing data securely in the backing directory. This involves deriving keys for symmetric encryption (e.g., AES) and handling file creation with encrypted metadata, ensuring seamless read/write operations without exposing plaintext. Such implementations support modes like forward (decrypt on read) or reverse (encrypt on write), with restrictions like session-specific access to prevent concurrent modifications.[22]
Remote access scenarios, such as an FTP-backed file system, leverage Dokan to map network listings to local directory views. The OpenDirectory callback resolves directory enumerations by querying the FTP server (e.g., via LIST commands) and populating FindFileData structures with file attributes from the response, allowing Windows Explorer to browse remote contents as if local. Tools like FTPUSE demonstrate this by using Dokan to mount FTP servers as drive letters, handling uploads/downloads through WriteFile and ReadFile callbacks that invoke FTP PUT/GET protocols. This enables transparent integration of remote storage without native Windows FTP mapping limitations.[23]
Integration with Dokan typically begins in C or C++ by linking the Dokan library (dokan.lib) and defining a PDOKAN_OPERATIONS structure with callback pointers, followed by calling DokanMain to mount the filesystem. For example:
c
DOKAN_OPTIONS dokanOptions = {0};
dokanOptions.Version = DOKAN_VERSION;
dokanOptions.MountPoint = L"M:\\";
dokanOptions.Options |= DOKAN_OPTION_DEBUG; // Example option
DOKAN_OPERATIONS dokanOperations = {0};
dokanOperations.ReadFile = MirrorReadFile; // Assign callbacks
// ... other callbacks
NTSTATUS status = DokanMain(&dokanOptions, &dokanOperations);
DOKAN_OPTIONS dokanOptions = {0};
dokanOptions.Version = DOKAN_VERSION;
dokanOptions.MountPoint = L"M:\\";
dokanOptions.Options |= DOKAN_OPTION_DEBUG; // Example option
DOKAN_OPERATIONS dokanOperations = {0};
dokanOperations.ReadFile = MirrorReadFile; // Assign callbacks
// ... other callbacks
NTSTATUS status = DokanMain(&dokanOptions, &dokanOperations);
Wrappers like Dokan.NET simplify this for managed languages, exposing similar operations via IDokanOperations interface and methods like DokanNet.Dokan.Start for mounting. Developers should ensure Visual C++ redistributables are included for runtime compatibility.[15][24]
Common pitfalls include handling large files, as the BufferLength parameter in ReadFile and WriteFile is limited to DWORD (4 GB maximum per call), requiring implementations to support multiple sequential calls without assuming single-operation completion. Failure to manage offsets correctly can lead to data corruption or incomplete transfers, particularly with memory-mapped files or applications performing large I/O. Testing with the provided mirror.exe sample—invoked as mirror.exe /r C:\source /l M—helps validate behavior under various loads, simulating real-world access patterns.[25]
For starter projects, developers can reference the official samples on the Dokany GitHub repository, including mirror and other utilities, along with the wiki for callback details and build instructions.[4]
Dokan.NET Wrapper
The Dokan.NET wrapper is an open-source .NET binding for the Dokan Library, hosted on GitHub under the repository dokan-dev/dokan-dotnet, enabling developers to create virtual file systems using C# and other managed languages without the need for kernel-mode drivers.[24] This binding provides C# classes that mirror core Dokan structures, such as DokanOptions for configuring mount options like drive letters and thread counts, and interfaces for handling file system operations.[26] Distributed via NuGet as the DokanNet package, it supports .NET Framework 4.6 and later, as well as .NET Standard 2.0/2.1 and .NET 8.0/9.0, allowing broad compatibility within the .NET ecosystem.[24]
Key classes in Dokan.NET include the Dokan class, which manages the mounting and unmounting of virtual drives by invoking the underlying Dokan library, and the IDokanOperations (or IDokanOperations2 for advanced async support) interface, which developers implement to define callbacks for file system events such as CreateFile, ReadFile, WriteFile, and DeleteFile.[27] These callbacks correspond to core Dokan API operations, providing a managed abstraction over the native interface described in the library's API structure.[27] By implementing this interface, developers can respond to file I/O requests in user-mode code, ensuring operations like file creation and reading are handled in a type-safe manner.[24]
Dokan.NET offers advantages for .NET developers by facilitating user-mode file system development in a managed environment, which inherently provides garbage collection for memory safety and simplifies debugging compared to native code.[2] This enables easier integration with .NET frameworks and libraries, such as using ASP.NET to back file systems with web services or data streams.[26] The wrapper aligns closely with the core Dokan Library versions, supporting Dokany 2.x releases; its latest version, 2.3.0.3, is compatible with Dokany 2.3.0.1000 and above, ensuring synchronization with ongoing library updates as of October 2024.[28]
A basic usage example involves implementing the IDokanOperations interface for a simple in-memory file system and mounting it via the Dokan class. The following C# snippet illustrates a minimal setup for an in-memory file system that supports basic file creation and reading (full implementations require handling additional operations like enumeration and deletion):
csharp
using DokanNet;
using DokanNet.Logging;
using System.IO;
public class InMemoryFS : IDokanOperations
{
private readonly Dictionary<string, byte[]> _files = new Dictionary<string, byte[]>();
public NTStatus CreateFile(string filename, FileAccess access, FileShare share, FileMode mode, FileAttributes attributes, FileOptions options, ref IDokanFileInfo info)
{
if (mode == FileMode.CreateNew && !_files.ContainsKey(filename))
{
_files[filename] = new byte[0];
info.Context = filename; // Store filename in context
return NTStatus.Success;
}
return NTStatus.AccessDenied;
}
public NTStatus ReadFile(string filename, byte[] buffer, out int bytesRead, long offset, ref IDokanFileInfo info)
{
if (info.Context is string fileName && _files.TryGetValue(fileName, out byte[] content))
{
int readLength = (int)Math.Min(buffer.Length, content.Length - offset);
Array.Copy(content, offset, buffer, 0, readLength);
bytesRead = readLength;
return NTStatus.Success;
}
bytesRead = 0;
return NTStatus.NotFound;
}
// Implement other required methods (e.g., WriteFile, CloseFile, etc.) with similar logic
public NTStatus WriteFile(string filename, byte[] buffer, out int bytesWritten, long offset, ref IDokanFileInfo info)
{
bytesWritten = 0;
return NTStatus.NotImplemented; // Extend for write support
}
// Placeholder for other interface methods
public NTStatus Cleanup(string filename, ref IDokanFileInfo info) => NTStatus.Success;
public NTStatus CloseFile(string filename, ref IDokanFileInfo info) => NTStatus.Success;
public NTStatus DeleteFile(string filename, ref IDokanFileInfo info) => NTStatus.Success;
public NTStatus DeleteDirectory(string filename, ref IDokanFileInfo info) => NTStatus.Success;
public NTStatus GetFileInformation(string filename, out FileInformation fileInfo, ref IDokanFileInfo info)
{
fileInfo = new FileInformation { FileName = filename, Length = 0 };
return NTStatus.Success;
}
public NTStatus GetVolumeInformation(out string volumeLabel, out FileSystemFeatures features, out string fileSystemName, ref IDokanFileInfo info)
{
volumeLabel = "InMemoryFS";
features = FileSystemFeatures.CaseSensitiveSearch;
fileSystemName = "INMEM";
return NTStatus.Success;
}
// Additional methods omitted for brevity; see full interface docs
}
class Program
{
static void Main()
{
var options = new [DokanOptions](/page/DokanOptions)
{
DriveLetter = 'Z',
ThreadCount = 1,
Options = [DokanOptions.MountManager](/page/DokanOptions.MountManager) | [DokanOptions.CurrentSession](/page/DokanOptions.CurrentSession) | [DokanOptions.KeepAlive](/page/DDokanOptions.KeepAlive),
Logger = new [ConsoleLogger](/page/ConsoleLogger)("InMemoryFS")
};
using var fs = new [InMemoryFS](/page/InMemoryFS)();
var result = [Dokan](/page/Dokan).Mount(options, fs);
Console.WriteLine($"Mount result: {result}");
Console.ReadLine(); // Keep running
[Dokan](/page/Dokan).RemoveMountPoint(options.DriveLetter);
}
}
using DokanNet;
using DokanNet.Logging;
using System.IO;
public class InMemoryFS : IDokanOperations
{
private readonly Dictionary<string, byte[]> _files = new Dictionary<string, byte[]>();
public NTStatus CreateFile(string filename, FileAccess access, FileShare share, FileMode mode, FileAttributes attributes, FileOptions options, ref IDokanFileInfo info)
{
if (mode == FileMode.CreateNew && !_files.ContainsKey(filename))
{
_files[filename] = new byte[0];
info.Context = filename; // Store filename in context
return NTStatus.Success;
}
return NTStatus.AccessDenied;
}
public NTStatus ReadFile(string filename, byte[] buffer, out int bytesRead, long offset, ref IDokanFileInfo info)
{
if (info.Context is string fileName && _files.TryGetValue(fileName, out byte[] content))
{
int readLength = (int)Math.Min(buffer.Length, content.Length - offset);
Array.Copy(content, offset, buffer, 0, readLength);
bytesRead = readLength;
return NTStatus.Success;
}
bytesRead = 0;
return NTStatus.NotFound;
}
// Implement other required methods (e.g., WriteFile, CloseFile, etc.) with similar logic
public NTStatus WriteFile(string filename, byte[] buffer, out int bytesWritten, long offset, ref IDokanFileInfo info)
{
bytesWritten = 0;
return NTStatus.NotImplemented; // Extend for write support
}
// Placeholder for other interface methods
public NTStatus Cleanup(string filename, ref IDokanFileInfo info) => NTStatus.Success;
public NTStatus CloseFile(string filename, ref IDokanFileInfo info) => NTStatus.Success;
public NTStatus DeleteFile(string filename, ref IDokanFileInfo info) => NTStatus.Success;
public NTStatus DeleteDirectory(string filename, ref IDokanFileInfo info) => NTStatus.Success;
public NTStatus GetFileInformation(string filename, out FileInformation fileInfo, ref IDokanFileInfo info)
{
fileInfo = new FileInformation { FileName = filename, Length = 0 };
return NTStatus.Success;
}
public NTStatus GetVolumeInformation(out string volumeLabel, out FileSystemFeatures features, out string fileSystemName, ref IDokanFileInfo info)
{
volumeLabel = "InMemoryFS";
features = FileSystemFeatures.CaseSensitiveSearch;
fileSystemName = "INMEM";
return NTStatus.Success;
}
// Additional methods omitted for brevity; see full interface docs
}
class Program
{
static void Main()
{
var options = new [DokanOptions](/page/DokanOptions)
{
DriveLetter = 'Z',
ThreadCount = 1,
Options = [DokanOptions.MountManager](/page/DokanOptions.MountManager) | [DokanOptions.CurrentSession](/page/DokanOptions.CurrentSession) | [DokanOptions.KeepAlive](/page/DDokanOptions.KeepAlive),
Logger = new [ConsoleLogger](/page/ConsoleLogger)("InMemoryFS")
};
using var fs = new [InMemoryFS](/page/InMemoryFS)();
var result = [Dokan](/page/Dokan).Mount(options, fs);
Console.WriteLine($"Mount result: {result}");
Console.ReadLine(); // Keep running
[Dokan](/page/Dokan).RemoveMountPoint(options.DriveLetter);
}
}
This example mounts an in-memory file system at drive Z:, where files are stored in a dictionary; extending it for full functionality involves implementing remaining IDokanOperations methods.[24][27]
FUSE Wrapper
The FUSE wrapper in Dokany is a library that enables compatibility between the FUSE (Filesystem in Userspace) API, originally designed for Linux, and the Dokan user-mode file system framework on Windows. This wrapper, implemented as the dokanfuse.dll module, allows developers to port existing FUSE-based file systems to Windows by translating high-level FUSE operations into Dokan callbacks, facilitating cross-platform reuse without requiring kernel-mode drivers.[5]
At its core, the wrapper maps methods from the FUSE fuse_operations structure—such as getattr, read, and readdir—to equivalent Dokan functions that interact with Windows NT APIs like ZwCreateFile and ReadFile. This translation layer handles the differences in operation semantics, ensuring that FUSE file system logic can invoke Dokan services transparently. The supported mappings are outlined in the following table, which covers key operations for file creation, reading, directory enumeration, and more:
| FUSE Method(s) | Dokan Method(s) | Notes |
|---|
| mknod, create, open, mkdir, opendir | ZwCreateFile | Handles creation and opening |
| release, releasedir | Cleanup | Manages release |
| read | ReadFile | Reads data |
| write | WriteFile | Writes data |
| flush | FlushFileBuffers | Flushes buffers |
| readdir | FindFiles | Enumerates directory |
| utimens | SetFileAttributes | Sets timestamps |
| getattr | GetFileInformation | Retrieves attributes |
| access | GetFileSecurity | Checks permissions |
| unlink | DeleteFile | Deletes files |
| rmdir | DeleteDirectory | Removes directories |
| rename | MoveFile | Renames or moves |
| truncate, ftruncate | SetEndOfFile | Truncates files |
| lock | LockFile, UnlockFile | Manages locking |
| chmod, chown | SetFileSecurity | Sets security |
| statfs | GetDiskFreeSpace, GetVolumeInformation | Retrieves stats |
To port a FUSE file system, developers recompile the source code using a compatible Windows toolchain such as MSVC, Cygwin, or MinGW-w64, linking against the Dokan FUSE library (e.g., via -lcygdokanfuse1 for Cygwin builds). FUSE methods are then implemented to call the mapped Dokan equivalents, with adjustments for Windows-specific behaviors like file paths and error codes; for instance, FUSE's readdir is routed to Dokan's FindFiles for directory listing. This process typically involves minimal code changes beyond recompilation and header adaptations, such as using FUSE_STAT structures instead of standard stat. The wrapper is included by default in the main Dokany source repository and installers.[5]
One primary benefit of the FUSE wrapper is the ability to leverage established FUSE codebases on Windows, avoiding full rewrites and accelerating development for cross-platform file systems. For example, it has enabled ports of utilities like SSHFS for remote mounting over SSH and EncFS for transparent encryption, allowing these tools to run natively on Windows mounts without proprietary drivers.[5][29][30]
However, the wrapper has limitations, as it does not support full FUSE compatibility, particularly lacking direct integration with low-level APIs like fuse_lowlevel.h. Certain features are unsupported or emulated imperfectly, including accurate timestamps for '.' and '..' entries, full symlink resolution on Windows, and Unix-style permissions, which are mapped to NTFS security descriptors but may not preserve exact semantics. Recompilation is mandatory for each target environment, and some advanced FUSE extensions remain unavailable.[5]
Practical examples include porting the standard FUSE sample fusexmp.c, which can be compiled on Windows as gcc fusexmp.c -lcygdokanfuse1 -o fusexmp.exe to create a basic echo file system mountable via Dokan. More complex ports, such as adapting SSHFS for Windows-based remote access or EncFS for local encrypted volumes, demonstrate the wrapper's utility in real-world scenarios, with binaries distributed through community efforts.[5]