dokan-dotnet icon indicating copy to clipboard operation
dokan-dotnet copied to clipboard

🐞 Issue: Corrupted or Access Denied When Opening PDF via Adobe Reader on Dokan Virtual Drive Summary:

Open dorbacao opened this issue 3 months ago • 4 comments

I'm using Dokan.NET to build a virtual file system. In CreateFile, I fetch PDF bytes from a remote server, save them to disk, and create a FileStream, storing it in info.Context. In ReadFile, I retrieve this stream, set its position using offset, and copy data into the buffer with stream.Read(buffer.Span).

Problem:

When I double-click the PDF file from the virtual drive, Windows copies it to a temporary folder and attempts to open it with Adobe Reader, but the app shows "access denied" or "file corrupted." However, if I manually open the copied file, it’s intact and opens correctly.

Note:

This disk-based approach was implemented only to help isolate the issue. My original design used a service that streamed file chunks on demand, but that didn’t work reliably with Adobe Reader, so I switched to this method for clearer diagnostics.

Relevant Code:

csharp // CreateFile File.WriteAllBytes(path, fileBytesFromServer); info.Context = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);

// ReadFile stream.Position = offset; bytesRead = stream.Read(buffer.Span); Request:

I’d like to know if there are known limitations or best practices for serving large binary files (like PDFs) via Dokan.NET, especially when accessed by applications like Adobe Reader that perform multiple concurrent reads.

dorbacao avatar Sep 23 '25 22:09 dorbacao

A couple of things to check.

Synchronization. Create a sync block around the read call to avoid situations with multiple reads reading from the same stream with collisions with setting position etc. Or alternatively, switch to using RandomAccess class methods instead of the FileStream which is more efficient and supports specifying an offset directly and is thread safe.

Check for timeouts. Reset timeout regularly for original request during lengthy operations such as downloading files. Otherwise, opening files will effectively fail for calling applications if they take too long time even though your file is actually downloaded successfully.

LTRData avatar Sep 24 '25 06:09 LTRData

I initially tried using a locking strategy for synchronization, but I wasn’t successful. I’ll now explore using RandomAccess instead to see if it better suits my needs. Thank you for your help! I'll be back to share my feedback.

dorbacao avatar Oct 01 '25 17:10 dorbacao

I used the RandomAccess strategy to read files in a thread-safe way, but I'm still experiencing the same issue. When I copy new images, all of them appear to have the same binary content when read. However, if I open the copied file directly from the temp folder, the image is correct. I get the binary file from api when CreateFile method is call.

This suggests the problem is in the ReadFile method.

public NtStatus ReadFile(ReadOnlyNativeMemory<char> fileNamePtr, NativeMemory<byte> buffer,
out int bytesRead, long offset, ref DokanFileInfo info)
{
    bytesRead = 0;
    string fileName = fileNamePtr.ToString();

    logger.LogInformation("ReadFile: {FileName}, Offset: {Offset}, BufferSize: {BufferSize}",
        fileName, offset, buffer.Length);

    try
    {
        if (info.Context is not FileStream stream)
        {
            logger.LogWarning("Contexto inválido ou ausente para: {FileName}");
            return NtStatus.ObjectNameNotFound;
        }

        long fileLength = stream.Length;

        if (offset >= fileLength)
        {
            logger.LogInformation("EOF atingido para: {FileName}");
            return NtStatus.Success;
        }

        int availableBytes = (int)(fileLength - offset);
        int bytesToRead = Math.Min(buffer.Length, availableBytes);

        // Leitura direta com RandomAccess
        int read = RandomAccess.Read(stream.SafeFileHandle, buffer.Span[..bytesToRead], offset);
        bytesRead = read;


        return NtStatus.Success;
    }
    catch (Exception ex)
    {
        logger.LogError(ex, "ReadFile failed for {FileName} at offset {Offset}", fileName, offset);
        return NtStatus.Error;
    }
}

dorbacao avatar Oct 17 '25 11:10 dorbacao

Could you try with DokanNetMirror sample application and create a Dokan mirror drive for a directory with PDF files and see whether it works with Adobe Reader to open a PDF through that mirror drive? Just to isolate the issue and find out whether it is something in Dokan itself or if there is something with timing, caching, file size/attributes etc handling in your particular implementation.

LTRData avatar Oct 17 '25 12:10 LTRData