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