public NtStatus FindFilesWithPattern(string fileName, string searchPattern, out IList <FileInformation> files,
                                      IDokanFileInfo info)
 {
     info.TryResetTimeout(60000);
     files = FindFilesHelper(fileName, searchPattern);
     return(Trace(nameof(FindFilesWithPattern), fileName, info, DokanResult.Success));
 }
 public NtStatus GetFileInformation(string fileName, out FileInformation fileInfo, IDokanFileInfo info)
 {
     // may be called with info.Context == null, but usually it isn't
     if (fileName.EndsWith("*"))
     {
         fileName = fileName.TrimEnd('*', '/', '\\');
         if (string.IsNullOrWhiteSpace(fileName))
         {
             fileName = "/";
         }
     }
     info.TryResetTimeout(60000);
     _ReadableFileSystem.GetFileInformation(fileName, out var fileInfo2);
     if (fileInfo2 != null)
     {
         fileInfo = (FileInformation)fileInfo2;
         return(Trace(nameof(GetFileInformation), fileName, info, DokanResult.Success));
     }
     else
     {
         fileInfo = default;
         return(Trace(nameof(GetFileInformation), fileName, info, DokanResult.PathNotFound));
     }
 }
예제 #3
0
        public NtStatus CreateFile(string fileName, FileAccess access, FileShare share, FileMode mode, FileOptions options, FileAttributes attributes, IDokanFileInfo info)
        {
            var result = NtStatus.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, NtStatus.NotADirectory, access, share, mode, options,
                                                 attributes));
                                }
                            }
                            catch (Exception)
                            {
                                return(Trace(nameof(CreateFile), fileName, info, DokanResult.FileNotFound, access, share, mode, options,
                                             attributes));
                            }
                            return(Trace(nameof(CreateFile), fileName, info, DokanResult.PathNotFound, access, share, mode, options,
                                         attributes));
                        }

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

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

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

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

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

                try
                {
                    pathIsDirectory = Directory.Exists(filePath);
                    pathExists      = pathIsDirectory || File.Exists(filePath);
                    var fileStatus = _repository.GetFileStatus(filePath);
                    fileisAnnexed = fileStatus == GinRepository.FileStatus.InAnnex ||
                                    fileStatus == GinRepository.FileStatus.InAnnexModified;
                }
                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, DokanResult.AccessDenied, access, share, mode, options,
                                             attributes));
                            }

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

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

                        //If the file is annexed and the driver definitely wants to open it, retrieve it.
                        if (fileisAnnexed)
                        {
                            var a       = info.TryResetTimeout(30000); //Annex operations take time;
                            var success = _repository.RetrieveFile(filePath);
                        }
                    }
                    else
                    {
                        return(Trace(nameof(CreateFile), fileName, info, DokanResult.FileNotFound, access, share, mode, options, attributes
                                     ));
                    }
                    break;

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

                case FileMode.Truncate:
                    if (!pathExists)
                    {
                        return(Trace(nameof(CreateFile), fileName, info, DokanResult.FileNotFound, access, share, mode, options, attributes
                                     ));
                    }
                    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
                {
                    if (info.Context is FileStream fileStream)
                    {
                        // returning AccessDenied cleanup and close won't be called
                        fileStream.Dispose();
                        info.Context = null;
                    }

                    return(Trace(nameof(CreateFile), fileName, info, DokanResult.AccessDenied, access, share, mode, options, attributes
                                 ));
                }
                catch (DirectoryNotFoundException)
                {
                    return(Trace(nameof(CreateFile), fileName, info, DokanResult.PathNotFound, access, share, mode, options, attributes
                                 ));
                }
                catch (Exception ex)
                {
                    var hr = (uint)Marshal.GetHRForException(ex);
                    switch (hr)
                    {
                    case 0x80070020:     //Sharing violation
                        return(Trace(nameof(CreateFile), fileName, info, DokanResult.SharingViolation, access, share, mode, options, attributes
                                     ));

                    default:
                        throw;
                    }
                }
            }

            return(Trace(nameof(CreateFile), fileName, info, result, access, share, mode, options, attributes));
        }