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)); } }
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)); }