Exemple #1
0
        public NtStatus CreateFile(string fileName, DokanNet.FileAccess access, FileShare share, FileMode mode, FileOptions options, FileAttributes attributes, DokanFileInfo info)
        {
            try
            {
                var ret = UnsafeCreateFile(fileName, access, share, mode, options, attributes, info);
                return(ret);
            }
            catch (UnauthorizedAccessException) // don't have access rights
            {
                (info.Context as LayeredContext)?.Dispose();

                return(DokanResult.AccessDenied);
            }
            catch (DirectoryNotFoundException)
            {
                (info.Context as LayeredContext)?.Dispose();

                return(DokanResult.PathNotFound);
            }
            catch (Exception ex)
            {
                (info.Context as LayeredContext)?.Dispose();

                var hr = (uint)Marshal.GetHRForException(ex);
                switch (hr)
                {
                case 0x80070020:     //Sharing violation
                    return(DokanResult.SharingViolation);

                default:
                    throw;
                }
            }
        }
        protected virtual NtStatus Trace(string method, string fileName, IDokanFileInfo info,
                                         DokanNet.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);
        }
        public Result CreateFile(string fileName, DokanNet.FileAccess access, FileShare share, FileMode mode, FileOptions options, FileAttributes attributes, IDokanFileInfo info)
        {
            var result   = ResultStatus.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(new Result(ResultStatus.NotADirectory));
                                }
                            }
                            catch (Exception)
                            {
                                return(new Result(ResultStatus.FileNotFound));
                            }
                            return(new Result(ResultStatus.PathNotFound));
                        }

                        _ = new DirectoryInfo(filePath).EnumerateFileSystemInfos().Any();
                        // you can't list the directory
                        break;

                    case FileMode.CreateNew:
                        if (Directory.Exists(filePath))
                        {
                            return(new Result(ResultStatus.FileExists));
                        }

                        try
                        {
                            File.GetAttributes(filePath).HasFlag(FileAttributes.Directory);
                            return(new Result(ResultStatus.AlreadyExists));
                        }
                        catch (IOException)
                        {
                        }

                        Directory.CreateDirectory(GetPath(fileName));
                        break;
                    }
                }
                catch (UnauthorizedAccessException)
                {
                    return(new Result(ResultStatus.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(new Result(ResultStatus.AccessDenied));
                            }

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

                            return(new Result(ResultStatus.Success));
                        }
                    }
                    else
                    {
                        return(new Result(ResultStatus.FileNotFound));
                    }
                    break;

                case FileMode.CreateNew:
                    if (pathExists)
                    {
                        return(new Result(ResultStatus.FileExists));
                    }
                    break;

                case FileMode.Truncate:
                    if (!pathExists)
                    {
                        return(new Result(ResultStatus.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 = ResultStatus.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(new Result(ResultStatus.AccessDenied));
                }
                catch (DirectoryNotFoundException)
                {
                    return(new Result(ResultStatus.PathNotFound));
                }
                catch (Exception ex)
                {
                    var hr = (uint)Marshal.GetHRForException(ex);
                    switch (hr)
                    {
                    case 0x80070020:     //Sharing violation
                        return(new Result(ResultStatus.SharingViolation));

                    default:
                        throw;
                    }
                }
            }
            return(new Result(result));
        }
Exemple #4
0
        public NtStatus UnsafeCreateFile(string fileName, DokanNet.FileAccess access, FileShare share, FileMode mode, FileOptions options, FileAttributes attributes, DokanFileInfo info)
        {
            string writePath    = GetWritePath(fileName);
            string readOnlyPath = GetReadOnlyPath(fileName);

            if (info.IsDirectory)
            {
                if (mode == FileMode.CreateNew)
                {
                    if (Directory.Exists(writePath))
                    {
                        return(DokanResult.FileExists);
                    }
                    else if (File.Exists(writePath))
                    {
                        return(DokanResult.AlreadyExists);
                    }
                    else if (Directory.Exists(readOnlyPath))
                    {
                        return(DokanResult.FileExists);
                    }
                    else if (File.Exists(readOnlyPath))
                    {
                        return(DokanResult.AlreadyExists);
                    }

                    info.Context = new LayeredDirectoryContext(fileName)
                    {
                        WriteDirInfo = Directory.CreateDirectory(writePath)
                    };
                    return(DokanResult.Success);
                }
                else if (mode == FileMode.Open)
                {
                    var context = new LayeredDirectoryContext(fileName);

                    if (Directory.Exists(writePath))
                    {
                        context.WriteDirInfo = new DirectoryInfo(writePath);
                    }
                    else if (File.Exists(writePath))
                    {
                        return(DokanResult.NotADirectory);
                    }

                    if (Directory.Exists(readOnlyPath))
                    {
                        context.ReadOnlyDirInfo = new DirectoryInfo(readOnlyPath);
                    }
                    else if (context.WriteDirInfo == null)
                    {
                        if (File.Exists(readOnlyPath))
                        {
                            return(DokanResult.NotADirectory);
                        }
                        else
                        {
                            return(DokanResult.PathNotFound);
                        }
                    }

                    info.Context = context;
                    return(DokanResult.Success);
                }
                else
                {
                    // unkown operation
                    return(DokanResult.Unsuccessful);
                }
            }
            else
            {
                var writable        = false;
                var pathExists      = false;
                var pathIsDirectory = Directory.Exists(writePath);

                if (pathIsDirectory)
                {
                    pathExists = true;
                }
                else if (File.Exists(writePath))
                {
                    writable   = true;
                    pathExists = true;
                }
                else
                {
                    if (pathIsDirectory = Directory.Exists(readOnlyPath))
                    {
                        pathExists      = true;
                        pathIsDirectory = true;
                    }
                    else
                    {
                        pathExists = File.Exists(readOnlyPath);
                    }
                }

                var readAttributes = (access & ReadAttributes) == 0;
                var readAccess     = (access & DataWriteAccess) == 0;

                switch (mode)
                {
                case FileMode.Open:
                    if (!pathExists)
                    {
                        return(DokanResult.FileNotFound);
                    }
                    else
                    {
                        if (pathIsDirectory)
                        {
                            info.IsDirectory = true;

                            if ((access & FileAccess.Delete) == FileAccess.Delete &&
                                (access & FileAccess.Synchronize) != FileAccess.Synchronize)
                            {
                                // it is a DeleteFile request on a directory
                                return(DokanResult.AccessDenied);
                            }

                            // call it again, with the IsDirectory set to true
                            return(UnsafeCreateFile(fileName, access, share, mode, options, attributes, info));
                        }
                        else if (readAttributes)
                        {
                            info.Context = new LayeredReadAttributesContext(fileName, writable ? writePath : readOnlyPath, pathIsDirectory);
                            return(DokanResult.Success);
                        }
                    }
                    break;

                case FileMode.CreateNew:
                    if (writable)
                    {
                        if (pathExists)
                        {
                            return(DokanResult.FileExists);
                        }
                    }
                    writable = true;

                    break;

                case FileMode.Create:
                    writable = true;
                    break;

                case FileMode.Truncate:
                    if (!pathExists)
                    {
                        return(DokanResult.FileNotFound);
                    }
                    break;

                case FileMode.OpenOrCreate:
                    if (!pathExists)
                    {
                        writable = true;
                    }
                    break;

                default:
                    throw new Exception($"Unhandled FileMode {mode.ToString("g")}");
                }

                if (writable)
                {
                    var path = Path.GetDirectoryName(writePath);
                    if (!Directory.Exists(path))
                    {
                        Directory.CreateDirectory(path);
                    }
                }
                else if (!readAccess)
                {
                    var path = Path.GetDirectoryName(writePath);
                    if (!Directory.Exists(path))
                    {
                        Directory.CreateDirectory(path);
                    }

                    File.Copy(readOnlyPath, writePath, true);

                    FileInfo finfo = new FileInfo(readOnlyPath);
                    File.SetCreationTime(writePath, finfo.CreationTime);
                    File.SetLastAccessTime(writePath, finfo.LastAccessTime);
                    File.SetLastWriteTime(writePath, finfo.LastWriteTime);

                    writable = true;
                }

                LayeredFileContext context = new LayeredFileContext(fileName, writable ? writePath : readOnlyPath, writable);
                info.Context = context;

                try
                {
                    context.Stream = new FileStream(writable ? writePath : readOnlyPath, mode,
                                                    readAccess ? System.IO.FileAccess.Read : System.IO.FileAccess.ReadWrite, share, 4096, options);
                }
                catch (Exception ex)
                {
                    var hr = (uint)Marshal.GetHRForException(ex);
                    switch (hr)
                    {
                    case 0x80070020:     //Sharing violation
                        return(DokanResult.SharingViolation);

                    default:
                        throw;
                    }
                }

                if (mode == FileMode.CreateNew || mode == FileMode.Create) // files are always created as Archive
                {
                    attributes |= FileAttributes.Archive;
                    context.SetAttributes(attributes);
                }

                return(DokanResult.Success);
            }
        }
Exemple #5
0
 public abstract NtStatus CreateFile(string fileName, DokanNet.FileAccess access, FileShare share, FileMode mode, FileOptions options, FileAttributes attributes, DokanFileInfo info);
 public NtStatus CreateFile(string fileName, DokanNet.FileAccess access, FileShare share, FileMode mode, FileOptions options, FileAttributes attributes, DokanFileInfo info)
 {
     /*
      * WARNING: THIS BREAKS MJFS PATH RESOLUTION AND MAY CAUSE BSODS
      *
      * string basePath = FileSystemHelper.lastBasePath; // spoof it
      *
      * if (Path.GetFileName(fileName).Trim() != "" && basePath != null) {
      *
      *      var path = basePath + Path.GetFileName(fileName);
      *      if (!info.IsDirectory) {
      *              // We don't do directories
      *              bool pathExists = true;
      *              bool pathIsDirectory = false;
      *
      *              bool readWriteAttributes = (access & DataAccess) == 0;
      *              bool readAccess = (access & DataWriteAccess) == 0;
      *
      *              try {
      *                      pathExists = (Directory.Exists(path) || File.Exists(path));
      *                      pathIsDirectory = File.GetAttributes(path).HasFlag(FileAttributes.Directory);
      *              } catch (IOException) { }
      *
      *              switch (mode) {
      *                      case FileMode.Open:
      *
      *                              if (pathExists) {
      *                                      if (readWriteAttributes || pathIsDirectory)
      *                                      // check if driver only wants to read attributes, security info, or open directory
      *                                      {
      *                                              if (pathIsDirectory && (access & FileAccess.Delete) == FileAccess.Delete
      *                                                      && (access & FileAccess.Synchronize) != FileAccess.Synchronize) //It is a DeleteFile request on a directory
      *                                                      return DokanResult.AccessDenied;
      *
      *                                              info.IsDirectory = pathIsDirectory;
      *                                              info.Context = new object();
      *                                              // must set it to someting if you return DokanError.Success
      *
      *                                              return DokanResult.Success;
      *                                      }
      *                              } else {
      *                                      return DokanResult.FileNotFound;
      *                              }
      *                              break;
      *
      *                      case FileMode.CreateNew:
      *                              if (pathExists)
      *                                      return DokanResult.FileExists;
      *                              break;
      *
      *                      case FileMode.Truncate:
      *                              if (!pathExists)
      *                                      return DokanResult.FileNotFound;
      *                              break;
      *
      *                      default:
      *                              break;
      *              }
      *
      *              try {
      *                      info.Context = new FileStream(path, mode, readAccess ? System.IO.FileAccess.Read : System.IO.FileAccess.ReadWrite, share, 4096, options);
      *
      *                      if (mode == FileMode.CreateNew
      || mode == FileMode.Create) //Files are always created as Archive
      ||                             attributes |= FileAttributes.Archive;
      ||                     File.SetAttributes(path, attributes);
      ||             } catch (UnauthorizedAccessException) // don't have access rights
      ||               {
      ||                     return DokanResult.AccessDenied;
      ||             } catch (DirectoryNotFoundException) {
      ||                     return DokanResult.PathNotFound;
      ||             } catch (Exception ex) {
      ||                     uint hr = (uint)Marshal.GetHRForException(ex);
      ||                     switch (hr) {
      ||                             case 0x80070020: //Sharing violation
      ||                                     return DokanResult.SharingViolation;
      ||                             default:
      ||                                     throw ex;
      ||                     }
      ||             }
      ||     }
      ||     return DokanResult.Success;
      ||} else {
      ||     info.IsDirectory = true;
      ||     info.Context = new object();
      ||     return DokanResult.Success;
      ||}*/
     return(DokanResult.Success);
 }
Exemple #7
0
        public NtStatus CreateFile(string fileName, DokanNet.FileAccess access, FileShare share, FileMode mode, FileOptions options, FileAttributes attributes, IDokanFileInfo info)
        {
            var result   = DokanResult.Success;
            var filePath = GetDiskPath(fileName);

            if (info.IsDirectory)
            {
                try
                {
                    switch (mode)
                    {
                    case FileMode.Open:
                        if (!Directory.Exists(filePath))
                        {
                            try
                            {
                                if (!File.GetAttributes(filePath).HasFlag(FileAttributes.Directory))
                                {
                                    return(DokanResult.NotADirectory);
                                }
                            }
                            catch (Exception)
                            {
                                return(DokanResult.FileNotFound);
                            }
                            return(DokanResult.PathNotFound);
                        }

                        new DirectoryInfo(filePath).EnumerateFileSystemInfos().Any();
                        // you can't list the directory
                        break;

                    case FileMode.CreateNew:
                        if (Directory.Exists(filePath))
                        {
                            return(DokanResult.FileExists);
                        }

                        try
                        {
                            File.GetAttributes(filePath).HasFlag(FileAttributes.Directory);
                            return(DokanResult.AlreadyExists);
                        }
                        catch (IOException)
                        {
                        }

                        Directory.CreateDirectory(GetDiskPath(fileName));
                        break;
                    }
                }
                catch (UnauthorizedAccessException)
                {
                    return(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 = File.GetAttributes(filePath).HasFlag(FileAttributes.Directory);
                }
                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(DokanResult.AccessDenied);
                            }

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

                            return(DokanResult.Success);
                        }
                    }
                    else
                    {
                        return(DokanResult.FileNotFound);
                    }
                    break;

                case FileMode.CreateNew:
                    if (pathExists)
                    {
                        return(DokanResult.FileExists);
                    }
                    break;

                case FileMode.Truncate:
                    if (!pathExists)
                    {
                        return(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;
                    }

                    if (mode == FileMode.CreateNew || mode == FileMode.Create) //Files are always created as Archive
                    {
                        attributes |= FileAttributes.Archive;
                    }
                    File.SetAttributes(filePath, attributes);
                }
                catch (UnauthorizedAccessException) // don't have access rights
                {
                    return(DokanResult.AccessDenied);
                }
                catch (DirectoryNotFoundException)
                {
                    return(DokanResult.PathNotFound);
                }
                catch (Exception ex)
                {
                    var hr = (uint)Marshal.GetHRForException(ex);
                    switch (hr)
                    {
                    case 0x80070020:     //Sharing violation
                        return(DokanResult.SharingViolation);

                    default:
                        throw;
                    }
                }
            }
            return(result);
        }