Dokan Dotnet SQL New Folder

75 views
Skip to first unread message

corey gashlin

unread,
Jul 23, 2021, 3:33:08 PM7/23/21
to Dokan
Hello all - 

I am using Dokan DOTNET. I have it hooked into MSSQL and it is working with listing files and directories. 

However, In testing I have it set to a empty directory and it displays but when I double click to open it. I want it to go to an empty space for me to put files into etc... However it just seems to navigate to the main root drive I have. My files open up correctly just not my directories. 

Any advice would be appreciated. 
I do plan on sharing this project once completed as I am working on a virtual file system with integration of WebDav/SqlLite and MSSQL. Online/Offiline file system. 


Thank You,


Adrien JUND

unread,
Jul 23, 2021, 4:34:02 PM7/23/21
to do...@googlegroups.com
Hi,

Could you explain how you are using dokan and share maybe some code ?
It feels like you are using the dokan mirror sample that mirrors the root drive into a folder.

Best regards,
Liryna

--
You received this message because you are subscribed to the Google Groups "Dokan" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dokan+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/dokan/ea04f774-91ce-4fc6-b728-b32ee266fec6n%40googlegroups.com.

corey gashlin

unread,
Jul 26, 2021, 10:41:11 AM7/26/21
to Dokan
So this is my test enviorment. I looked at the mirror code example as well as a few others for this. My biggest thing at the moment is just trying ot navigate to a folder or an empty folder.. Since I am deriving my file structure from a SQL DB

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.AccessControl;
using System.Text;
using System.Threading.Tasks;
using DokanNet;
using DokanNet.Logging;
using static DokanNet.FormatProviders;
using static DriveMap.ProgressBar;
using FileAccess = DokanNet.FileAccess;



namespace DriveMap
{
    class OCIDOKAN : IDokanOperations

    {
        public static string directoryStr;
        private Dictionary<String, FileCaching> FileCache = new Dictionary<String, FileCaching>();

        private const FileAccess DataAccess = FileAccess.ReadData | FileAccess.WriteData | FileAccess.AppendData |
                                            FileAccess.Execute |
                                            FileAccess.GenericExecute | FileAccess.GenericWrite |
                                            FileAccess.GenericRead;

        private const FileAccess DataWriteAccess = FileAccess.WriteData | FileAccess.AppendData |
                                                   FileAccess.Delete |
                                                   FileAccess.GenericWrite;
        string ConnectionString;

        private ConsoleLogger logger = new ConsoleLogger("[OCIDOKAN] ");


        public OCIDOKAN()
        {
            ConnectionString = "Data Source=192.168.0.31;User ID=ocisql;Password=Emagdne1212";
        }

        public void Cleanup(string fileName, IDokanFileInfo info)
        {
            Console.WriteLine("Cleanup Stage 1");
            Console.WriteLine(GetPath(fileName));
            Console.WriteLine("---------------------");
        }

        public void CloseFile(string fileName, IDokanFileInfo info)
        {
            Console.WriteLine("CloseFile");
        }

        public NtStatus CreateFile(string fileName, DokanNet.FileAccess access, FileShare share, FileMode mode, FileOptions options, FileAttributes attributes, IDokanFileInfo info)
        {
            var result = DokanResult.Success;
            var filePath = GetPath(fileName);

            if (info.IsDirectory)
            {
                try
                {
                    switch (mode)
                    {
                        case FileMode.Open:
                            if (!Directory.Exists(filePath))
                            {
                                try
                                {
                                    if (!File.GetAttributes(filePath).HasFlag(FileAttributes.Directory))
                                        return Trace(nameof(CreateFile), fileName, info, access, share, mode, options,
                                            attributes, DokanResult.Success);
                                }
                                catch (Exception)
                                {
                                    return Trace(nameof(CreateFile), fileName, info, access, share, mode, options,
                                        attributes, DokanResult.FileNotFound);
                                }
                                return Trace(nameof(CreateFile), fileName, info, access, share, mode, options,
                                    attributes, DokanResult.PathNotFound);
                            }

                            new DirectoryInfo(filePath).EnumerateFileSystemInfos(@"C:\");
                            // you can't list the directory
                            break;

                        case FileMode.CreateNew:
                            if (Directory.Exists(filePath))
                                return Trace(nameof(CreateFile), fileName, info, access, share, mode, options,
                                    attributes, DokanResult.FileExists);

                            try
                            {
                                File.GetAttributes(filePath).HasFlag(FileAttributes.Directory);
                                return Trace(nameof(CreateFile), fileName, info, access, share, mode, options,
                                    attributes, DokanResult.AlreadyExists);
                            }
                            catch (IOException)
                            {
                            }

                            Directory.CreateDirectory(GetPath(fileName));
                            break;
                    }
                }
                catch (UnauthorizedAccessException)
                {
                    return Trace(nameof(CreateFile), fileName, info, access, share, mode, options, attributes,
                        DokanResult.AccessDenied);
                }
            }
            else
            {
                var pathExists = true;
                var pathIsDirectory = false;

                var readWriteAttributes = (access & DataAccess) == 0;
                var readAccess = (access & DataWriteAccess) == 0;

                try
                {
                    pathExists = (Directory.Exists(filePath) || File.Exists(filePath));
                    pathIsDirectory = pathExists ? File.GetAttributes(filePath).HasFlag(FileAttributes.Directory) : false;
                }
                catch (IOException)
                {
                }

                switch (mode)
                {
                    case FileMode.Open:

                        if (pathExists)
                        {
                            // check if driver only wants to read attributes, security info, or open directory
                            if (readWriteAttributes || pathIsDirectory)
                            {
                                if (pathIsDirectory && (access & FileAccess.Delete) == FileAccess.Delete
                                    && (access & FileAccess.Synchronize) != FileAccess.Synchronize)
                                    //It is a DeleteFile request on a directory
                                    return Trace(nameof(CreateFile), fileName, info, access, share, mode, options,
                                        attributes, DokanResult.AccessDenied);

                                info.IsDirectory = pathIsDirectory;
                                info.Context = new object();
                                // must set it to something if you return DokanError.Success

                                return Trace(nameof(CreateFile), fileName, info, access, share, mode, options,
                                    attributes, DokanResult.Success);
                            }
                        }
                        else
                        {
                            return Trace(nameof(CreateFile), fileName, info, access, share, mode, options, attributes,
                                DokanResult.FileNotFound);
                        }
                        break;

                    case FileMode.CreateNew:
                        if (pathExists)
                            return Trace(nameof(CreateFile), fileName, info, access, share, mode, options, attributes,
                                DokanResult.FileExists);
                        break;

                    case FileMode.Truncate:
                        if (!pathExists)
                            return Trace(nameof(CreateFile), fileName, info, access, share, mode, options, attributes,
                                DokanResult.FileNotFound);
                        break;
                }

                try
                {
                    info.Context = new FileStream(filePath, mode,
                        readAccess ? System.IO.FileAccess.Read : System.IO.FileAccess.ReadWrite, share, 4096, options);

                    if (pathExists && (mode == FileMode.OpenOrCreate
                                       || mode == FileMode.Create))
                        result = DokanResult.AlreadyExists;

                    bool fileCreated = mode == FileMode.CreateNew || mode == FileMode.Create || (!pathExists && mode == FileMode.OpenOrCreate);
                    if (fileCreated)
                    {
                        FileAttributes new_attributes = attributes;
                        new_attributes |= FileAttributes.Archive; // Files are always created as Archive
                        // FILE_ATTRIBUTE_NORMAL is override if any other attribute is set.
                        new_attributes &= ~FileAttributes.Normal;
                        File.SetAttributes(filePath, new_attributes);
                    }
                }
                catch (UnauthorizedAccessException) // don't have access rights
                {
                    if (info.Context is FileStream fileStream)
                    {
                        // returning AccessDenied cleanup and close won't be called,
                        // so we have to take care of the stream now
                        fileStream.Dispose();
                        info.Context = null;
                    }
                    return Trace(nameof(CreateFile), fileName, info, access, share, mode, options, attributes,
                        DokanResult.AccessDenied);
                }
                catch (DirectoryNotFoundException)
                {
                    return Trace(nameof(CreateFile), fileName, info, access, share, mode, options, attributes,
                        DokanResult.PathNotFound);
                }
                catch (Exception ex)
                {
                    var hr = (uint)Marshal.GetHRForException(ex);
                    switch (hr)
                    {
                        case 0x80070020: //Sharing violation
                            return Trace(nameof(CreateFile), fileName, info, access, share, mode, options, attributes,
                                DokanResult.SharingViolation);
                        default:
                            throw;
                    }
                }
            }
            return Trace(nameof(CreateFile), fileName, info, access, share, mode, options, attributes,
                result);

         
        }

        public NtStatus DeleteDirectory(string fileName, IDokanFileInfo info)
        {
            using (SqlConnection conn = new SqlConnection(ConnectionString))
            {
                SqlCommand SP = new SqlCommand();
                SP.Connection = conn;
                SP.CommandText = "DELETE FROM OCI_STORAGE_WEBDAV WHERE FILENAME=@FILENAME";
                SP.Parameters.AddWithValue("@FILENAME", fileName);
                conn.Open();
                try
                {
                    
                    SP.ExecuteNonQuery(); //on MoveFile can raise error due directory is exists
                }
                catch
                {
                }
            }
            return DokanResult.Success;
        }

        public NtStatus DeleteFile(string fileName, IDokanFileInfo info)
        {
            throw new NotImplementedException();
        }
        public NtStatus CreateDirectory(string filename, DokanFileInfo info)
        {
            using (SqlConnection conn = new SqlConnection(ConnectionString))
            {
                SqlCommand SP = new SqlCommand();
                SP.Connection = conn;
                SP.CommandType = CommandType.StoredProcedure;
                SP.CommandText = "CreateDirectory";
                SP.Parameters.AddWithValue("@filename", filename);
                conn.Open();
                try
                {
                    SP.ExecuteNonQuery(); //on MoveFile can raise error due directory is exists
                }
                catch
                {
                }
            }
            return DokanResult.Success;
        }

        public NtStatus FindFiles(string fileName, out IList<FileInformation> files, IDokanFileInfo info)
        {
            //This creates the directory listing... As of curent this just lists the main directory indicated from SQL Database. 
            //This queries MSSQL Database for basic file information and applies it and returns it as a LIST to Dokan to create the filesystem. 

            IList<FileInformation> ListOfShit = new List<FileInformation>();
            try
            {
                using (SqlConnection conn = new SqlConnection(ConnectionString))
                {
                    SqlCommand CMD = new SqlCommand();
                    CMD.CommandText = @"SELECT * FROM OCI_STORAGE_WEBDAV";
                    CMD.CommandType = System.Data.CommandType.Text;
                    CMD.Connection = conn;
                    conn.Open();
                    using (SqlDataReader reader = CMD.ExecuteReader())
                    {
                        while (reader.Read())
                        {
                            FileInformation fi = new FileInformation();

                            lock (FileCache)
                            {
                                if (reader[6].ToString() == "Directory")
                                {

                                    FileInformation di = new FileInformation();
                                    //if (FileCache.ContainsKey(di.FileName) == true)
                                    // {
                                    di.Attributes = FileAttributes.Directory;
                                    di.FileName = reader[1].ToString();
                                    di.Length = 0;
                                    di.CreationTime = (DateTime)reader[3];
                                    di.LastAccessTime = (DateTime)reader[4];
                                    di.LastWriteTime = (DateTime)reader[5];
                                   
                                    // }

                                    ListOfShit.Add(di);
                                }
                                if (reader[6].ToString() == "Archive")
                                {


                                    //if (FileCache.ContainsKey(fi.FileName) == true)
                                    //{
                                    fi.Attributes = FileAttributes.Archive;
                                    fi.FileName = reader[1].ToString();
                                    fi.Length = (long)reader[2];
                                    fi.CreationTime = (DateTime)reader[3];
                                    fi.LastAccessTime = (DateTime)reader[4];
                                    fi.LastWriteTime = (DateTime)reader[5];
                                    // }


                                    ListOfShit.Add(fi);
                                }
                            }



                        }
                        files = ListOfShit;
                        return DokanResult.Success;
                    }




                }
            }
            catch
            {
                files = null;
                return DokanResult.Error;
            }


        }

        public NtStatus FindFilesWithPattern(string fileName, string searchPattern, out IList<FileInformation> files, IDokanFileInfo info)
        {
            files = null;
            return DokanResult.NotImplemented;
        }

        public NtStatus FindStreams(string fileName, out IList<FileInformation> streams, IDokanFileInfo info)
        {
            throw new NotImplementedException();
        }

        public NtStatus FlushFileBuffers(string fileName, IDokanFileInfo info)
        {
            throw new NotImplementedException();
        }

        public NtStatus GetDiskFreeSpace(out long freeBytesAvailable, out long totalNumberOfBytes, out long totalNumberOfFreeBytes, IDokanFileInfo info)
        {

            freeBytesAvailable = 3298535977703 - GetUsedSpace();
            totalNumberOfBytes = 3298535977703;
            totalNumberOfFreeBytes = 3298535977703 - GetUsedSpace();
            return DokanResult.Success;
        }

        public NtStatus GetFileInformation(string fileName, out FileInformation fileInfo, IDokanFileInfo info)
        {
            // This extracts the MetaData from the system

            var filePath = GetPath(fileName);
            FileSystemInfo finfo = new FileInfo(filePath);
            fileInfo = new FileInformation();
            if (!finfo.Exists)
                finfo = new DirectoryInfo(filePath);

            if (File.Exists(filePath))
            {
                FileInfo fi = new FileInfo(filePath);
                fileInfo.Length = fi.Length;
                fileInfo.Attributes = fi.Attributes;
                fileInfo.CreationTime = fi.CreationTime;
                fileInfo.FileName = fi.FullName;
                fileInfo.LastAccessTime = fi.LastAccessTime;
                fileInfo.LastWriteTime = fi.LastWriteTime;
                return Trace(nameof(GetFileInformation), fileName, info, DokanResult.Success);
            }
            else if (Directory.Exists(filePath))
            {
                info.IsDirectory = true;

                DirectoryInfo fi = new DirectoryInfo(filePath);
                fileInfo.Attributes = fi.Attributes;
                fileInfo.CreationTime = fi.CreationTime;
                fileInfo.FileName = fi.FullName;
                fileInfo.LastAccessTime = fi.LastAccessTime;
                fileInfo.LastWriteTime = fi.LastWriteTime;

                return Trace(nameof(GetFileInformation), fileName, info, DokanResult.Success);
            }




            return Trace(nameof(GetFileInformation), fileName, info, DokanResult.Success);
        }

        public NtStatus GetFileSecurity(string fileName, out FileSystemSecurity security, AccessControlSections sections, IDokanFileInfo info)
        {
            throw new NotImplementedException();
        }

        public NtStatus GetVolumeInformation(out string volumeLabel, out FileSystemFeatures features, out string fileSystemName, out uint maximumComponentLength, IDokanFileInfo info)
        {
            volumeLabel = "OCI Project Directory";
            fileSystemName = "OCIFS";
            maximumComponentLength = 256;


            features = FileSystemFeatures.CasePreservedNames | FileSystemFeatures.CaseSensitiveSearch |
                       FileSystemFeatures.PersistentAcls | FileSystemFeatures.SupportsRemoteStorage |
                       FileSystemFeatures.UnicodeOnDisk;

            return Trace(nameof(GetVolumeInformation), null, info, DokanResult.Success, "out " + volumeLabel,
                "out " + features.ToString(), "out " + fileSystemName);
        }

        public NtStatus LockFile(string fileName, long offset, long length, IDokanFileInfo info)
        {
            throw new NotImplementedException();
        }

        public NtStatus Mounted(IDokanFileInfo info)
        {
            return DokanResult.Success;
        }

        public NtStatus MoveFile(string oldName, string newName, bool replace, IDokanFileInfo info)
        {
            throw new NotImplementedException();
        }

        public NtStatus ReadFile(string fileName, byte[] buffer, out int bytesRead, long offset, IDokanFileInfo info)
        {
            if (info.Context == null) // memory mapped read
            {
                using (var stream = new FileStream(GetPath(fileName), FileMode.Open, System.IO.FileAccess.Read))
                {
                    stream.Position = offset;
                    bytesRead = stream.Read(buffer, 0, buffer.Length);
                }
            }
            else // normal read
            {
                var stream = info.Context as FileStream;
                lock (stream) //Protect from overlapped read
                {
                    stream.Position = offset;
                    bytesRead = stream.Read(buffer, 0, buffer.Length);
                }
            }
            return Trace(nameof(ReadFile), fileName, info, DokanResult.Success, "out " + bytesRead.ToString(),
                offset.ToString(CultureInfo.InvariantCulture));
        }

        public NtStatus SetAllocationSize(string fileName, long length, IDokanFileInfo info)
        {
            throw new NotImplementedException();
        }

        public NtStatus SetEndOfFile(string fileName, long length, IDokanFileInfo info)
        {
            throw new NotImplementedException();
        }

        public NtStatus SetFileAttributes(string fileName, FileAttributes attributes, IDokanFileInfo info)
        {
            throw new NotImplementedException();
        }

        public NtStatus SetFileSecurity(string fileName, FileSystemSecurity security, AccessControlSections sections, IDokanFileInfo info)
        {
            throw new NotImplementedException();
        }

        public NtStatus SetFileTime(string fileName, DateTime? creationTime, DateTime? lastAccessTime, DateTime? lastWriteTime, IDokanFileInfo info)
        {
            throw new NotImplementedException();
        }

        public NtStatus UnlockFile(string fileName, long offset, long length, IDokanFileInfo info)
        {
            throw new NotImplementedException();
        }

        public NtStatus Unmounted(IDokanFileInfo info)
        {
            FileCache.Clear();
            return DokanResult.Success;
        }

        public NtStatus WriteFile(string fileName, byte[] buffer, out int bytesWritten, long offset, IDokanFileInfo info)
        {


            var append = offset == -1;
            if (info.Context == null)
            {
                using (var stream = new FileStream(GetPath(fileName), append ? FileMode.Append : FileMode.Open, System.IO.FileAccess.Write))
                {
                    if (!append) // Offset of -1 is an APPEND: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-writefile
                    {
                        stream.Position = offset;
                    }
                    stream.Write(buffer, 0, buffer.Length);
                    bytesWritten = buffer.Length;
                }
            }
            else
            {
                var stream = info.Context as FileStream;
                lock (stream) //Protect from overlapped write
                {
                    if (append)
                    {
                        if (stream.CanSeek)
                        {
                            stream.Seek(0, SeekOrigin.End);
                        }
                        else
                        {
                            bytesWritten = 0;
                            return Trace(nameof(WriteFile), fileName, info, DokanResult.Error, "out " + bytesWritten,
                                offset.ToString(CultureInfo.InvariantCulture));
                        }
                    }
                    else
                    {
                        stream.Position = offset;
                    }
                    stream.Write(buffer, 0, buffer.Length);
                }
                bytesWritten = buffer.Length;
            }
            return Trace(nameof(WriteFile), fileName, info, DokanResult.Success, "out " + bytesWritten.ToString(),
                offset.ToString(CultureInfo.InvariantCulture));
        }

        public Int64 GetUsedSpace()
        {
            string CX1 = "Data Source=192.168.0.31;User ID=ocisql;Password=Emagdne1212";

            string sql = @"select sum(length) from oci_storage_webdav";
            string variable;
            using (var connection = new SqlConnection(CX1))
            using (var command = new SqlCommand(sql, connection))
            {

                connection.Open();

                return Convert.ToInt64(command.ExecuteNonQuery() + 10737412742);



            }
        }
        public string GetPath(string filename)
        {

            string CX1 = "Data Source=192.168.0.31;User ID=ocisql;Password=Emagdne1212";

            string sql = @"SELECT [location] FROM OCI_STORAGE_WEBDAV where [filename] = @filename and [filename] <> ''";
            string variable;
            using (var connection = new SqlConnection(CX1))
            using (var command = new SqlCommand(sql, connection))
            {
                command.Parameters.AddWithValue("@filename", filename);
                connection.Open();
                directoryStr = (string)command.ExecuteScalar() + filename;
                //return directoryStr;

                return @"C:\Users\cgashlin\Desktop\DokanTest\" + filename;

            }


        }

        protected NtStatus Trace(string method, string fileName, IDokanFileInfo info, NtStatus result,
             params object[] parameters)
        {
#if TRACE
            var extraParameters = parameters != null && parameters.Length > 0
                ? ", " + string.Join(", ", parameters.Select(x => string.Format(DefaultFormatProvider, "{0}", x)))
                : string.Empty;

            logger.Debug(DokanFormat($"{method}('{fileName}', {info}{extraParameters}) -> {result}"));
#endif

            return result;
        }
        class FileCaching
        {
            public MemoryStream MemStream;
            public FileInformation FileInfo;

        }
        private static FileCaching FillFileCache(String filename)
        {
            FileCaching fc = new FileCaching();
            fc.MemStream = new MemoryStream();
            fc.FileInfo = new FileInformation();
            fc.FileInfo.CreationTime = DateTime.Now;
            fc.FileInfo.LastAccessTime = DateTime.Now;
            fc.FileInfo.LastWriteTime = DateTime.Now;
            fc.FileInfo.Length = 0;
            fc.FileInfo.FileName = filename;
            return fc;
        }
        private NtStatus Trace(string method, string fileName, IDokanFileInfo info,
            FileAccess access, FileShare share, FileMode mode, FileOptions options, FileAttributes attributes,
            NtStatus result)
        {
#if TRACE
            logger.Debug(
                DokanFormat(
                    $"{method}('{fileName}', {info}, [{access}], [{share}], [{mode}], [{options}], [{attributes}]) -> {result}"));
#endif

            return result;
        }
    }
}


Adrien JUND

unread,
Jul 26, 2021, 12:23:36 PM7/26/21
to do...@googlegroups.com
If I understood correctly, you see your root drive when you enter a folder that is at the root of your virtual drive right ?
Then somewhere in this code, there is something that does list your root drive and return the information to Dokan for a subfolder listing.
I am not able to review your code right now. 
Try to use the software procmon to spy what is happening and when the listing is happening.

Reply all
Reply to author
Forward
0 new messages