Пример #1
0
        /// <inheritdoc/>
        public override bool CloseFileHandle(string path, LVFSContextInfo info)
        {
            // This is the same as Cleanup as there's only one thing that might need tidying, but according to a comment in the DokanNet Mirror example, there potentially are situations where only one of the two is called.
            try
            {
                object context;

                if (info.Context.TryGetValue(this, out context))
                {
                    (context as FileStream)?.Dispose();
                    info.Context.Remove(this);
                }

                if (info.DeleteOnClose)
                {
                    if (info.IsDirectory && Directory.Exists(ConvertPath(path)))
                    {
                        Directory.Delete(ConvertPath(path));
                    }
                    else if (File.Exists(ConvertPath(path)))
                    {
                        File.Delete(ConvertPath(path));
                    }
                }

                return(PredecessorCloseFileHandle(path, info));
            }
            catch (Exception)
            {
                // Because there're no checked exceptions in C#, I can't tell what might go wrong here and catch specific exceptions.
                PredecessorCloseFileHandle(path, info);
                return(false);
            }
        }
Пример #2
0
        /// <inheritdoc/>
        public override NtStatus FlushBuffers(string path, LVFSContextInfo info)
        {
            NtStatus result = DokanResult.Success;

            if (info.Context.ContainsKey(this))
            {
                try
                {
                    FileStream stream = info.Context[this] as FileStream;
                    if (stream != null)
                    {
                        stream.Flush();
                    }
                }
                catch (IOException)
                {
                    result = DokanResult.DiskFull;
                }
            }

            NtStatus predecessorResult = PredecessorFlushBuffers(path, info);

            if (result == DokanResult.Success && predecessorResult != DokanResult.Success)
            {
                return(predecessorResult);
            }
            else
            {
                return(result);
            }
        }
Пример #3
0
        /// <inheritdoc/>
        public override bool CleanupFileHandle(string path, LVFSContextInfo info)
        {
            try
            {
                object context;
                if (info.Context.TryGetValue(this, out context))
                {
                    (context as FileStream)?.Dispose();
                    info.Context.Remove(this);
                }

                if (info.DeleteOnClose)
                {
                    if (info.IsDirectory && Directory.Exists(ConvertPath(path)))
                    {
                        Directory.Delete(ConvertPath(path));
                    }
                    else if (File.Exists(ConvertPath(path)))
                    {
                        File.Delete(ConvertPath(path));
                    }
                }

                return(PredecessorCleanupFileHandle(path, info));
            }
            catch (Exception)
            {
                // Because there're no checked exceptions in C#, I can't tell what might go wrong here and catch specific exceptions.
                PredecessorCleanupFileHandle(path, info);
                return(false);
            }
        }
Пример #4
0
 /// <inheritdoc/>
 public override NtStatus SetLength(string path, long length, LVFSContextInfo info)
 {
     if (ControlsFile(path))
     {
         try
         {
             var stream = info.Context[this] as FileStream;
             if (stream != null)
             {
                 stream.SetLength(length);
             }
             else
             {
                 new FileStream(ConvertPath(path), FileMode.Open).SetLength(length);
             }
             return(DokanResult.Success);
         }
         catch (IOException)
         {
             return(DokanResult.DiskFull);
         }
         catch (UnauthorizedAccessException)
         {
             return(DokanResult.AccessDenied);
         }
     }
     else
     {
         return(PredecessorSetLength(path, length, info));
     }
 }
Пример #5
0
        /// <summary>
        /// Moves the file/directory from its current path to a new one, replacing any existing files only if replace is set.
        /// </summary>
        /// <param name="currentPath">The current path of the file/directory</param>
        /// <param name="newPath">The new path of the file/directory</param>
        /// <param name="replace">Whether to replace any existing file occupying the new path</param>
        /// <param name="info">Information concerning the context for this operation.</param>
        /// <returns><see cref="DokanResult.Success"/> if the file was moved. Otherwise, an appropriate error status.</returns>
        public NtStatus MoveFile(string currentPath, string newPath, bool replace, LVFSContextInfo info)
        {
            WritableSource writable = Last as WritableSource;

            if (writable != null)
            {
                return(writable.MoveFile(currentPath, newPath, replace, info));
            }
            else
            {
                return(DokanResult.AccessDenied);
            }
        }
Пример #6
0
        /// <summary>
        /// Clears any buffers for the context, and ensures any buffered data is written to the actual file.
        /// </summary>
        /// <param name="path">The path to the file whose buffers to flush</param>
        /// <param name="info">Information concerning the context for the operation</param>
        /// <returns><see cref="DokanResult.Success"/> if all buffers were flushed, If not, an appropriate error status.</returns>
        public NtStatus FlushBuffers(string path, LVFSContextInfo info)
        {
            WritableSource writable = Last as WritableSource;

            if (writable != null)
            {
                return(writable.FlushBuffers(path, info));
            }
            else
            {
                return(DokanResult.NotImplemented);
            }
        }
Пример #7
0
        /// <summary>
        /// Sets the length of the file.
        /// </summary>
        /// <param name="path">The path to the file</param>
        /// <param name="length">The new length of the file</param>
        /// <param name="info">Information concerning the context of this operation</param>
        /// <returns><see cref="DokanResult.Success"/> if the requested length is now the length of the file. If not, an appropriate error status.</returns>
        public NtStatus SetLength(string path, long length, LVFSContextInfo info)
        {
            WritableSource writable = Last as WritableSource;

            if (writable != null)
            {
                return(writable.SetLength(path, length, info));
            }
            else
            {
                return(DokanResult.AccessDenied);
            }
        }
Пример #8
0
        /// <summary>
        /// Sets the allocated size for the file. If this is less than the current length, trucate the file. If the file does not grow to fill this space before the handle is released, it may be freed.
        /// </summary>
        /// <param name="path">The path to the file</param>
        /// <param name="allocationSize">The new size to allocate</param>
        /// <param name="info">Information concerning the context for this operation</param>
        /// <returns><see cref="DokanResult.Success"/> if the allocation size was changed or already the correct value. If not, an appropriate error status.</returns>
        public NtStatus SetAllocatedSize(string path, long allocationSize, LVFSContextInfo info)
        {
            WritableSource writable = Last as WritableSource;

            if (writable != null)
            {
                return(writable.SetAllocatedSize(path, allocationSize, info));
            }
            else
            {
                return(DokanResult.AccessDenied);
            }
        }
Пример #9
0
 /// <inheritdoc/>
 public override NtStatus SetAllocatedSize(string path, long allocationSize, LVFSContextInfo info)
 {
     // C# offers no ability to allocate space for a file without actually setting its length, so this function cannot be implemented without calling native code. In the mirror example, this is implemented with incorrect semantics. Despite that, many operations require this to claim to work, so we return success whenever this is called.
     if (ControlsFile(path))
     {
         if (allocationSize < (info.Context[this] as FileStream).Length)
         {
             (info.Context[this] as FileStream).SetLength(allocationSize);
         }
         return(DokanResult.Success);
     }
     else
     {
         return(PredecessorSetAllocatedSize(path, allocationSize, info));
     }
 }
Пример #10
0
 /// <inheritdoc/>
 public override bool CleanupFileHandle(string path, LVFSContextInfo info)
 {
     try
     {
         object context;
         if (info.Context.TryGetValue(this, out context))
         {
             (context as FileStream)?.Dispose();
             info.Context.Remove(this);
         }
         return(true);
     }
     catch (Exception)
     {
         // Because there're no checked exceptions in C#, I can't tell what might go wrong here and catch specific exceptions.
         return(false);
     }
 }
Пример #11
0
 /// <inheritdoc/>
 public override bool CloseFileHandle(string path, LVFSContextInfo info)
 {
     // This is the same as Cleanup as there's only one thing that might need tidying, but according to a comment in the DokanNet Mirror example, there potentially are situations where only one of the two is called.
     try
     {
         object context;
         if (info.Context.TryGetValue(this, out context))
         {
             (context as FileStream)?.Dispose();
             info.Context.Remove(this);
         }
         return(true);
     }
     catch (Exception)
     {
         // Because there're no checked exceptions in C#, I can't tell what might go wrong here and catch specific exceptions.
         return(false);
     }
 }
Пример #12
0
        /// <summary>
        /// Sets the security attributes for the specified sections of the specified file or directory.
        /// </summary>
        /// <param name="path">The path to the file</param>
        /// <param name="security">The security to set</param>
        /// <param name="sections">The access control sections to change</param>
        /// <param name="info">Information concerning the context of this operation.</param>
        /// <returns><see cref="DokanResult.Success"/> if the operation was successful. If not, an appropriate error status.</returns>
        public NtStatus SetFileSecurity(string path, FileSystemSecurity security, AccessControlSections sections, LVFSContextInfo info)
        {
            WritableSource writable = Last as WritableSource;

            if (writable != null)
            {
                return(writable.SetFileSecurity(path, security, sections, info));
            }
            else
            {
                return(DokanResult.AccessDenied);
            }
        }
Пример #13
0
        /// <inheritdoc/>
        public override NtStatus CreateFileHandle(string path, DokanNet.FileAccess access, FileShare share, FileMode mode, FileOptions options, FileAttributes attributes, LVFSContextInfo info)
        {
            var filePath = ConvertPath(path);

            var isDirectory = Directory.Exists(filePath);
            var pathExists  = isDirectory || File.Exists(filePath);

            // Check this first for performance reasons. Keep checking it later in case anything's been meddled with
            if (!pathExists)
            {
                return(PredecessorCreateFileHandle(path, access, share, mode, options, attributes, info));
            }

            if (info.IsDirectory)
            {
                try
                {
                    switch (mode)
                    {
                    case FileMode.Open:
                        if (Directory.Exists(filePath))
                        {
                            // The original Dokan mirror this is based on called new DirectoryInfo(filePath).EnumerateFileSystemInfos().Any();, but did nothing with its result at this point
                            return(DokanResult.Success);
                        }
                        else if (File.Exists(filePath))
                        {
                            return(NtStatus.NotADirectory);
                        }
                        else
                        {
                            return(PredecessorCreateFileHandle(path, access, share, mode, options, attributes, info));
                        }

                    case FileMode.OpenOrCreate:
                        if (Directory.Exists(filePath))
                        {
                            return(DokanResult.Success);
                        }
                        else if (File.Exists(filePath))
                        {
                            return(DokanResult.FileExists);
                        }
                        else
                        {
                            return(PredecessorCreateFileHandle(path, access, share, mode, options, attributes, info));
                        }

                    case FileMode.CreateNew:
                        if (Directory.Exists(filePath))
                        {
                            return(DokanResult.AlreadyExists);
                        }
                        else if (File.Exists(filePath))
                        {
                            return(DokanResult.FileExists);
                        }
                        else
                        {
                            return(PredecessorCreateFileHandle(path, access, share, mode, options, attributes, info));
                        }

                    default:
                        if (Directory.Exists(filePath) || File.Exists(filePath))
                        {
                            return(DokanResult.AccessDenied);
                        }
                        else
                        {
                            return(PredecessorCreateFileHandle(path, access, share, mode, options, attributes, info));
                        }
                    }
                }
                catch (UnauthorizedAccessException)
                {
                    return(DokanResult.AccessDenied);
                }
            }
            else
            {
                switch (mode)
                {
                case FileMode.Open:
                    if (pathExists)
                    {
                        var dataAccess = DokanNet.FileAccess.ReadData | DokanNet.FileAccess.WriteData | DokanNet.FileAccess.AppendData | DokanNet.FileAccess.Execute | DokanNet.FileAccess.GenericExecute | DokanNet.FileAccess.GenericWrite | DokanNet.FileAccess.GenericRead;
                        var readWriteOnlyAttributes = (access & dataAccess) == 0;
                        if (isDirectory || readWriteOnlyAttributes)
                        {
                            if (isDirectory && access.HasFlag(DokanNet.FileAccess.Delete) && !access.HasFlag(DokanNet.FileAccess.Synchronize))
                            {
                                // It's a delete request on a directory.
                                return(DokanResult.AccessDenied);
                            }

                            info.IsDirectory = isDirectory;

                            return(DokanResult.Success);
                        }
                        else
                        {
                            // Go to the regular handler
                            break;
                        }
                    }
                    else
                    {
                        return(PredecessorCreateFileHandle(path, access, share, mode, options, attributes, info));
                    }

                case FileMode.OpenOrCreate:
                    if (pathExists)
                    {
                        // Go to the regular handler
                        break;
                    }
                    else
                    {
                        return(PredecessorCreateFileHandle(path, access, share, mode, options, attributes, info));
                    }

                case FileMode.CreateNew:
                    if (pathExists)
                    {
                        return(DokanResult.FileExists);
                    }
                    else
                    {
                        return(PredecessorCreateFileHandle(path, access, share, mode, options, attributes, info));
                    }

                case FileMode.Truncate:
                    if (pathExists)
                    {
                        return(DokanResult.AccessDenied);
                    }
                    else
                    {
                        return(PredecessorCreateFileHandle(path, access, share, mode, options, attributes, info));
                    }

                case FileMode.Create:
                    if (pathExists)
                    {
                        return(DokanResult.AccessDenied);
                    }
                    else
                    {
                        return(PredecessorCreateFileHandle(path, access, share, mode, options, attributes, info));
                    }

                case FileMode.Append:
                    if (pathExists)
                    {
                        return(DokanResult.AccessDenied);
                    }
                    else
                    {
                        return(PredecessorCreateFileHandle(path, access, share, mode, options, attributes, info));
                    }

                default:
                    // This code should never be reached
                    throw new ArgumentException("Unknown file mode: " + mode, nameof(mode));
                }

                try
                {
                    info.Context[this] = new FileStream(filePath, mode, System.IO.FileAccess.Read, share, 4096, options);

                    if (mode == FileMode.Open)
                    {
                        return(DokanResult.Success);
                    }
                    else
                    {
                        return(DokanResult.AlreadyExists);
                    }
                }
                catch (UnauthorizedAccessException)
                {
                    return(DokanResult.AccessDenied);
                }
                catch (DirectoryNotFoundException)
                {
                    return(DokanResult.PathNotFound);
                }
                catch (Exception ex)
                {
                    var hr = (uint)System.Runtime.InteropServices.Marshal.GetHRForException(ex);
                    switch (hr)
                    {
                    case 0x80070020:                             //Sharing violation
                        return(DokanResult.SharingViolation);

                    default:
                        throw;
                    }
                }
            }
        }
Пример #14
0
        /// <inheritdoc/>
        public override NtStatus SetFileSecurity(string path, FileSystemSecurity security, AccessControlSections sections, LVFSContextInfo info)
        {
            if (ControlsFile(path))
            {
                FileSystemSecurity actualSecurity;
                if (info.IsDirectory)
                {
                    actualSecurity = Directory.GetAccessControl(ConvertPath(path), sections);
                }
                else
                {
                    actualSecurity = File.GetAccessControl(ConvertPath(path), sections);
                }

                var desiredSddlForm = security.GetSecurityDescriptorSddlForm(sections);
                actualSecurity.SetSecurityDescriptorSddlForm(desiredSddlForm, sections);

                if (info.IsDirectory)
                {
                    Directory.SetAccessControl(ConvertPath(path), actualSecurity as DirectorySecurity);
                }
                else
                {
                    File.SetAccessControl(ConvertPath(path), actualSecurity as FileSecurity);
                }
                return(DokanResult.Success);
            }
            else
            {
                return(PredecessorSetFileSecurity(path, security, sections, info));
            }
        }
Пример #15
0
 /// <summary>
 /// Called when a file handle is requested
 /// </summary>
 /// <param name="path">The path to the file</param>
 /// <param name="access">The type of access required</param>
 /// <param name="share">The kind of access other filestreams can have</param>
 /// <param name="mode">The mode to open the file in</param>
 /// <param name="options">Advanced options for creating a FileStream</param>
 /// <param name="attributes">The attributes of the file</param>
 /// <param name="info">An LVFSinfo containing the context for the file handle and information on the file</param>
 /// <returns>An NtStatus explaining the success level of the operation. If mode is OpenOrCreate and Create, and the operation is successful opening an existing file, DokanResult.AlreadyExists is returned.</returns>
 public NtStatus CreateFileHandle(string path, DokanNet.FileAccess access, System.IO.FileShare share, System.IO.FileMode mode, System.IO.FileOptions options, System.IO.FileAttributes attributes, LVFSContextInfo info)
 {
     return(Last.CreateFileHandle(path, access, share, mode, options, attributes, info));
 }
Пример #16
0
        /// <inheritdoc/>
        public override bool ReadFile(string path, byte[] buffer, out int bytesRead, long offset, LVFSContextInfo info)
        {
            if (info != null && info.Context.ContainsKey(this))
            {
                var stream = info.Context[this] as FileStream;
                lock (stream)
                {
                    stream.Position = offset;
                    bytesRead       = stream.Read(buffer, 0, buffer.Length);
                }
                return(true);
            }
            else if (File.Exists(ConvertPath(path)))
            {
                using (var stream = new FileStream(ConvertPath(path), FileMode.Open, System.IO.FileAccess.Read))
                {
                    stream.Position = offset;

                    bytesRead = stream.Read(buffer, 0, buffer.Length);
                }
                return(true);
            }
            else
            {
                return(PredecessorReadFile(path, buffer, out bytesRead, offset, info));
            }
        }
Пример #17
0
        /// <inheritdoc/>
        public override NtStatus MoveFile(string currentPath, string newPath, bool replace, LVFSContextInfo info)
        {
            var fullCurrentPath = ConvertPath(currentPath);
            var fullNewPath     = ConvertPath(newPath);

            if (ControlsFile(currentPath))
            {
                try
                {
                    object context;
                    info.Context.TryGetValue(this, out context);
                    (context as FileStream)?.Dispose();
                    info.Context[this] = null;

                    // Maybe reopen file stream once file is moved.

                    if (!HasFile(newPath))
                    {
                        if (info.IsDirectory)
                        {
                            Directory.Move(fullCurrentPath, fullNewPath);
                        }
                        else
                        {
                            File.Move(fullCurrentPath, fullNewPath);
                        }

                        return(DokanResult.Success);
                    }
                    else if (replace)
                    {
                        // Delete the original if possible, but otherwise ignore it when it's in another layer as it doesn't affect the external behaviour of the VFS

                        // replace is incompatible with directories
                        if (info.IsDirectory)
                        {
                            return(DokanResult.AccessDenied);
                        }

                        if (ControlsFile(newPath))
                        {
                            try
                            {
                                File.Delete(fullNewPath);
                                File.Move(fullCurrentPath, fullNewPath);
                                return(DokanResult.Success);
                            }
                            catch (UnauthorizedAccessException)
                            {
                                return(DokanResult.AccessDenied);
                            }
                        }
                        else
                        {
                            // A predecessor source has the file to be replaced, so we can ignore it.
                            try
                            {
                                File.Move(fullCurrentPath, fullNewPath);
                                return(DokanResult.Success);
                            }
                            catch (UnauthorizedAccessException)
                            {
                                return(DokanResult.AccessDenied);
                            }
                        }
                    }
                    else
                    {
                        return(DokanResult.FileExists);
                    }
                }
                catch (UnauthorizedAccessException)
                {
                    return(DokanResult.AccessDenied);
                }
            }
            else
            {
                return(PredecessorMoveFile(currentPath, newPath, replace, info));
            }
        }
Пример #18
0
 /// <summary>
 /// To be called once all file handles for this context have been closed and released.
 /// </summary>
 /// <param name="path">The path to the file</param>
 /// <param name="info">The information for the context of this operation</param>
 /// <returns>True if the operation was successful</returns>
 public bool CloseFileHandle(string path, LVFSContextInfo info)
 {
     return(Last.CloseFileHandle(path, info));
 }
Пример #19
0
        /// <inheritdoc/>
        public override NtStatus CreateFileHandle(string path, DokanNet.FileAccess access, FileShare share, FileMode mode, FileOptions options, FileAttributes attributes, LVFSContextInfo info)
        {
            var controlsFile = ControlsFile(path);

            if (!controlsFile && PredecessorHasFile(path))
            {
                return(PredecessorCreateFileHandle(path, access, share, mode, options, attributes, info));
            }

            var convertedPath   = ConvertPath(path);
            var directoryExists = Directory.Exists(convertedPath);
            var fileExists      = File.Exists(convertedPath);

            if (info.IsDirectory)
            {
                try
                {
                    switch (mode)
                    {
                    case FileMode.Open:
                    {
                        if (directoryExists)
                        {
                            return(DokanResult.Success);
                        }
                        else if (fileExists)
                        {
                            return(NtStatus.NotADirectory);
                        }
                        else
                        {
                            return(PredecessorCreateFileHandle(path, access, share, mode, options, attributes, info));
                        }
                    }

                    case FileMode.CreateNew:
                    {
                        if (directoryExists)
                        {
                            return(DokanResult.AlreadyExists);
                        }
                        else if (fileExists)
                        {
                            return(DokanResult.FileExists);
                        }
                        else if (PredecessorHasFile(path))
                        {
                            return(DokanResult.AlreadyExists);
                        }
                        else
                        {
                            Directory.CreateDirectory(convertedPath);
                            return(DokanResult.Success);
                        }
                    }

                    case FileMode.OpenOrCreate:
                    {
                        if (directoryExists)
                        {
                            return(DokanResult.Success);
                        }
                        else if (fileExists)
                        {
                            return(NtStatus.NotADirectory);
                        }
                        else if (PredecessorHasFile(path))
                        {
                            return(PredecessorCreateFileHandle(path, access, share, mode, options, attributes, info));
                        }
                        else
                        {
                            Directory.CreateDirectory(convertedPath);
                            return(DokanResult.Success);
                        }
                    }

                    default:
                    {
                        // I don't think any other file modes can actually used with directories, so we should be free to die in any arbitrary way here. In fact, I don't think OpenOrCreate can actually be used with directories either, but the associated behaviour was simple enough, so I implemented it anyway.
                        return(DokanResult.NotImplemented);
                    }
                    }
                }
                catch (UnauthorizedAccessException)
                {
                    return(DokanResult.AccessDenied);
                }
            }
            else
            {
                switch (mode)
                {
                case FileMode.Open:
                {
                    if (fileExists || directoryExists)
                    {
                        var dataAccess = DokanNet.FileAccess.ReadData | DokanNet.FileAccess.WriteData | DokanNet.FileAccess.AppendData | DokanNet.FileAccess.Execute | DokanNet.FileAccess.GenericExecute | DokanNet.FileAccess.GenericWrite | DokanNet.FileAccess.GenericRead;
                        var readWriteOnlyAttributes = (access & dataAccess) == 0;

                        if (directoryExists || readWriteOnlyAttributes)
                        {
                            if (directoryExists && access.HasFlag(DokanNet.FileAccess.Delete) && !access.HasFlag(DokanNet.FileAccess.Synchronize))
                            {
                                // Delete request on (potentially) non-empty directory
                                return(DokanResult.AccessDenied);
                            }

                            info.IsDirectory = directoryExists;

                            return(DokanResult.Success);
                        }
                        else
                        {
                            // Go to the regular handler
                            break;
                        }
                    }
                    else
                    {
                        return(PredecessorCreateFileHandle(path, access, share, mode, options, attributes, info));
                    }
                }

                case FileMode.OpenOrCreate:
                case FileMode.Create:
                case FileMode.Append:
                {
                    if (fileExists || directoryExists)
                    {
                        // Go to the regular handler
                        break;
                    }
                    else if (PredecessorHasFile(path))
                    {
                        return(PredecessorCreateFileHandle(path, access, share, mode, options, attributes, info));
                    }
                    else
                    {
                        // Go to the regular handler
                        break;
                    }
                }

                case FileMode.CreateNew:
                {
                    if (fileExists || directoryExists || PredecessorHasFile(path))
                    {
                        return(DokanResult.AlreadyExists);
                    }
                    else
                    {
                        // Go to the regular handler
                        break;
                    }
                }

                case FileMode.Truncate:
                {
                    if (fileExists || directoryExists)
                    {
                        // Go to the regular handler
                        break;
                    }
                    else if (PredecessorHasFile(path))
                    {
                        return(PredecessorCreateFileHandle(path, access, share, mode, options, attributes, info));
                    }
                    else
                    {
                        return(DokanResult.FileNotFound);
                    }
                }

                default:
                    // This code should never be reached
                    throw new ArgumentException("Unknown file mode: " + mode, nameof(mode));
                }

                var dataWriteAccess = DokanNet.FileAccess.WriteData | DokanNet.FileAccess.AppendData | DokanNet.FileAccess.Delete | DokanNet.FileAccess.GenericWrite;
                var readAccessOnly  = (access & dataWriteAccess) == 0;

                try
                {
                    var result = DokanResult.Success;

                    if (!Directory.Exists(Path.GetDirectoryName(convertedPath)))
                    {
                        if (PredecessorHasDirectory(Path.GetDirectoryName(path)))
                        {
                            Directory.CreateDirectory(Path.GetDirectoryName(convertedPath));
                        }
                        else
                        {
                            return(DokanResult.PathNotFound);
                        }
                    }
                    info.Context[this] = new FileStream(convertedPath, mode, readAccessOnly ? System.IO.FileAccess.Read : System.IO.FileAccess.ReadWrite, share, 4096, options);

                    if ((fileExists || directoryExists) && (mode == FileMode.OpenOrCreate || mode == FileMode.Create))
                    {
                        result = DokanResult.AlreadyExists;
                    }

                    if (mode == FileMode.CreateNew || mode == FileMode.Create)
                    {
                        attributes |= FileAttributes.Archive;
                    }

                    File.SetAttributes(convertedPath, attributes);

                    return(result);
                }
                catch (UnauthorizedAccessException)
                {
                    return(DokanResult.AccessDenied);
                }
                catch (DirectoryNotFoundException)
                {
                    return(DokanResult.PathNotFound);
                }
                catch (Exception ex)
                {
                    var hr = (uint)System.Runtime.InteropServices.Marshal.GetHRForException(ex);
                    switch (hr)
                    {
                    case 0x80070020:                             //Sharing violation
                        return(DokanResult.SharingViolation);

                    default:
                        throw;
                    }
                }
            }
        }
Пример #20
0
 /// <summary>
 /// Gets the contents of the specified file starting at the specified offset and attempts to fill the buffer.
 /// </summary>
 /// <param name="path">The path to the file</param>
 /// <param name="buffer">The buffer to fill with the file contents</param>
 /// <param name="bytesRead">The actual number of bytes read from the file. This may be less than the length of the buffer if not enough data is available.</param>
 /// <param name="offset">The byte at which to start reading.</param>
 /// <param name="info">Holds the context for the operation and relevant information</param>
 /// <returns>A bool indicating whether the operation was successful</returns>
 public bool ReadFile(string path, byte[] buffer, out int bytesRead, long offset, LVFSContextInfo info)
 {
     return(Last.ReadFile(path, buffer, out bytesRead, offset, info));
 }
Пример #21
0
 /// <inheritdoc/>
 public override bool TryUnlockFileRegion(string path, long startOffset, long length, LVFSContextInfo info)
 {
     if (info.Context.ContainsKey(this))
     {
         try
         {
             (info.Context[this] as FileStream)?.Unlock(startOffset, length);
             return(true);
         }
         catch (IOException)
         {
             return(false);
         }
     }
     else
     {
         return(PredecessorTryUnlockFileRegion(path, startOffset, length, info));
     }
 }
Пример #22
0
 /// <summary>
 /// Unlocks a region of the specified file from the specified offset with the specified length if possible.
 /// </summary>
 /// <param name="path">The path to the file</param>
 /// <param name="startOffset">The offset at which the region to unlock starts</param>
 /// <param name="length">The length of the region to unlock</param>
 /// <param name="info">Holds the context for the operation and relevant information</param>
 /// <returns>True if the operation was successful, false if access was denied</returns>
 public bool TryUnlockFileRegion(string path, long startOffset, long length, LVFSContextInfo info)
 {
     return(Last.TryUnlockFileRegion(path, startOffset, length, info));
 }
Пример #23
0
        /// <inheritdoc/>
        public override NtStatus WriteFile(string path, byte[] buffer, out int bytesWritten, long offset, LVFSContextInfo info)
        {
            if (info.Context.ContainsKey(this) && info.Context[this] != null)
            {
                try
                {
                    var stream = info.Context[this] as FileStream;
                    lock (stream)
                    {
                        stream.Position = offset;
                        stream.Write(buffer, 0, buffer.Length);
                    }
                    bytesWritten = buffer.Length;

                    return(DokanResult.Success);
                }
                catch (UnauthorizedAccessException)
                {
                    bytesWritten = 0;
                    return(DokanResult.AccessDenied);
                }
                catch (IOException)
                {
                    bytesWritten = 0;
                    return(DokanResult.DiskFull);
                }
            }
            else if (ControlsFile(path))
            {
                using (var stream = new FileStream(ConvertPath(path), FileMode.Open, System.IO.FileAccess.Write))
                {
                    try
                    {
                        stream.Position = offset;
                        stream.Write(buffer, 0, buffer.Length);
                        bytesWritten = buffer.Length;
                    }
                    catch (UnauthorizedAccessException)
                    {
                        bytesWritten = 0;
                        return(DokanResult.AccessDenied);
                    }
                    catch (IOException)
                    {
                        bytesWritten = 0;
                        return(DokanResult.DiskFull);
                    }
                }
                return(DokanResult.Success);
            }
            else
            {
                return(PredecessorWriteFile(path, buffer, out bytesWritten, offset, info));
            }
        }
Пример #24
0
        /// <summary>
        /// Writes the contents of the buffer to the requested file, starting at the requested offset, and sets the bytes written value to the number of bytes successfully written to the file.
        /// </summary>
        /// <param name="path">The path to the file</param>
        /// <param name="buffer">A buffer containing the data to write</param>
        /// <param name="bytesWritten">The number of bytes transferred from the buffer to the file</param>
        /// <param name="offset">The offset at which to start the write</param>
        /// <param name="info">Information concerning the context of this operation.</param>
        /// <returns><see cref="DokanResult.Success"/> if the operation was successful. If not, an appropriate error status.</returns>
        public NtStatus WriteFile(string path, byte[] buffer, out int bytesWritten, long offset, LVFSContextInfo info)
        {
            WritableSource writable = Last as WritableSource;

            if (writable != null)
            {
                return(writable.WriteFile(path, buffer, out bytesWritten, offset, info));
            }
            else
            {
                bytesWritten = 0;
                return(DokanResult.AccessDenied);
            }
        }