public NTStatus CreateFile(out object handle, out FileStatus fileStatus, string path, AccessMask desiredAccess, FileAttributes fileAttributes, ShareAccess shareAccess, CreateDisposition createDisposition, CreateOptions createOptions, SecurityContext securityContext) { fileStatus = FileStatus.FILE_DOES_NOT_EXIST; // It is possible to have a named pipe that does not use RPC (e.g. MS-WSP), // However this is not currently needed by our implementation. RemoteService service = GetService(path); if (service != null) { // All instances of a named pipe share the same pipe name, but each instance has its own buffers and handles, // and provides a separate conduit for client/server communication. RPCPipeStream stream = new RPCPipeStream(service); handle = new FileHandle(path, false, stream, false); fileStatus = FileStatus.FILE_OPENED; return(NTStatus.STATUS_SUCCESS); } handle = null; return(NTStatus.STATUS_OBJECT_PATH_NOT_FOUND); }
/// <param name="fileName">Expression as described in [MS-FSA] 2.1.4.4</param> public NTStatus QueryDirectory(out List <QueryDirectoryFileInformation> result, object handle, string fileName, FileInformationClass informationClass) { result = null; FileHandle directoryHandle = (FileHandle)handle; if (!directoryHandle.IsDirectory) { return(NTStatus.STATUS_INVALID_PARAMETER); } if (fileName == String.Empty) { return(NTStatus.STATUS_INVALID_PARAMETER); } string path = directoryHandle.Path; bool findExactName = !ContainsWildcardCharacters(fileName); List <FileSystemEntry> entries; if (!findExactName) { try { entries = m_fileSystem.ListEntriesInDirectory(path); } catch (UnauthorizedAccessException) { return(NTStatus.STATUS_ACCESS_DENIED); } entries = GetFiltered(entries, fileName); // Windows will return "." and ".." when enumerating directory files. // The SMB1 / SMB2 specifications mandate that when zero entries are found, the server SHOULD / MUST return STATUS_NO_SUCH_FILE. // For this reason, we MUST include the current directory and/or parent directory when enumerating a directory // in order to diffrentiate between a directory that does not exist and a directory with no entries. FileSystemEntry currentDirectory = m_fileSystem.GetEntry(path); currentDirectory.Name = "."; FileSystemEntry parentDirectory = m_fileSystem.GetEntry(FileSystem.GetParentDirectory(path)); parentDirectory.Name = ".."; entries.Insert(0, parentDirectory); entries.Insert(0, currentDirectory); } else { path = FileSystem.GetDirectoryPath(path); FileSystemEntry entry = m_fileSystem.GetEntry(path + fileName); if (entry == null) { return(NTStatus.STATUS_NO_SUCH_FILE); } entries = new List <FileSystemEntry>(); entries.Add(entry); } try { result = FromFileSystemEntries(entries, informationClass); } catch (UnsupportedInformationLevelException) { return(NTStatus.STATUS_INVALID_INFO_CLASS); } return(NTStatus.STATUS_SUCCESS); }
public NTStatus GetFileInformation(out FileInformation result, object handle, FileInformationClass informationClass) { FileHandle fileHandle = (FileHandle)handle; string path = fileHandle.Path; FileSystemEntry entry; try { entry = m_fileSystem.GetEntry(path); } catch (Exception ex) { NTStatus status = ToNTStatus(ex); Log(Severity.Verbose, "GetFileInformation on '{0}' failed. {1}", path, status); result = null; return(status); } if (entry == null) { result = null; return(NTStatus.STATUS_NO_SUCH_FILE); } switch (informationClass) { case FileInformationClass.FileBasicInformation: { FileBasicInformation information = new FileBasicInformation(); information.CreationTime = entry.CreationTime; information.LastAccessTime = entry.LastAccessTime; information.LastWriteTime = entry.LastWriteTime; information.ChangeTime = entry.LastWriteTime; information.FileAttributes = GetFileAttributes(entry); result = information; return(NTStatus.STATUS_SUCCESS); } case FileInformationClass.FileStandardInformation: { FileStandardInformation information = new FileStandardInformation(); information.AllocationSize = (long)GetAllocationSize(entry.Size); information.EndOfFile = (long)entry.Size; information.Directory = entry.IsDirectory; information.DeletePending = fileHandle.DeleteOnClose; result = information; return(NTStatus.STATUS_SUCCESS); } case FileInformationClass.FileInternalInformation: { FileInternalInformation information = new FileInternalInformation(); result = information; return(NTStatus.STATUS_SUCCESS); } case FileInformationClass.FileEaInformation: { FileEaInformation information = new FileEaInformation(); information.EaSize = 0; result = information; return(NTStatus.STATUS_SUCCESS); } case FileInformationClass.FileAccessInformation: { result = null; return(NTStatus.STATUS_NOT_IMPLEMENTED); } case FileInformationClass.FileNameInformation: { FileNameInformation information = new FileNameInformation(); information.FileName = entry.Name; result = information; return(NTStatus.STATUS_SUCCESS); } case FileInformationClass.FilePositionInformation: { result = null; return(NTStatus.STATUS_NOT_IMPLEMENTED); } case FileInformationClass.FileFullEaInformation: { result = null; return(NTStatus.STATUS_NOT_IMPLEMENTED); } case FileInformationClass.FileModeInformation: { result = null; return(NTStatus.STATUS_NOT_IMPLEMENTED); } case FileInformationClass.FileAlignmentInformation: { result = null; return(NTStatus.STATUS_NOT_IMPLEMENTED); } case FileInformationClass.FileAllInformation: { FileAllInformation information = new FileAllInformation(); information.BasicInformation.CreationTime = entry.CreationTime; information.BasicInformation.LastAccessTime = entry.LastAccessTime; information.BasicInformation.LastWriteTime = entry.LastWriteTime; information.BasicInformation.ChangeTime = entry.LastWriteTime; information.BasicInformation.FileAttributes = GetFileAttributes(entry); information.StandardInformation.AllocationSize = (long)GetAllocationSize(entry.Size); information.StandardInformation.EndOfFile = (long)entry.Size; information.StandardInformation.Directory = entry.IsDirectory; information.StandardInformation.DeletePending = fileHandle.DeleteOnClose; information.NameInformation.FileName = entry.Name; result = information; return(NTStatus.STATUS_SUCCESS); } case FileInformationClass.FileAlternateNameInformation: { result = null; return(NTStatus.STATUS_NOT_IMPLEMENTED); } case FileInformationClass.FileStreamInformation: { // This information class is used to enumerate the data streams of a file or a directory. // A buffer of FileStreamInformation data elements is returned by the server. FileStreamInformation information = new FileStreamInformation(); FileStreamEntry streamEntry = new FileStreamEntry(); streamEntry.StreamSize = (long)entry.Size; streamEntry.StreamAllocationSize = (long)GetAllocationSize(entry.Size); streamEntry.StreamName = "::$DATA"; information.Entries.Add(streamEntry); result = information; return(NTStatus.STATUS_SUCCESS); } case FileInformationClass.FilePipeInformation: { result = null; return(NTStatus.STATUS_NOT_IMPLEMENTED); } case FileInformationClass.FilePipeLocalInformation: { result = null; return(NTStatus.STATUS_NOT_IMPLEMENTED); } case FileInformationClass.FilePipeRemoteInformation: { result = null; return(NTStatus.STATUS_NOT_IMPLEMENTED); } case FileInformationClass.FileCompressionInformation: { result = null; return(NTStatus.STATUS_NOT_IMPLEMENTED); } case FileInformationClass.FileNetworkOpenInformation: { FileNetworkOpenInformation information = new FileNetworkOpenInformation(); information.CreationTime = entry.CreationTime; information.LastAccessTime = entry.LastAccessTime; information.LastWriteTime = entry.LastWriteTime; information.ChangeTime = entry.LastWriteTime; information.AllocationSize = (long)GetAllocationSize(entry.Size); information.EndOfFile = (long)entry.Size; information.FileAttributes = GetFileAttributes(entry); result = information; return(NTStatus.STATUS_SUCCESS); } case FileInformationClass.FileAttributeTagInformation: { result = null; return(NTStatus.STATUS_NOT_IMPLEMENTED); } default: result = null; return(NTStatus.STATUS_INVALID_INFO_CLASS); } }
public NTStatus SetFileInformation(object handle, FileInformation information) { FileHandle fileHandle = (FileHandle)handle; if (information is FileBasicInformation) { FileBasicInformation basicInformation = (FileBasicInformation)information; bool isHidden = ((basicInformation.FileAttributes & FileAttributes.Hidden) > 0); bool isReadonly = (basicInformation.FileAttributes & FileAttributes.ReadOnly) > 0; bool isArchived = (basicInformation.FileAttributes & FileAttributes.Archive) > 0; try { m_fileSystem.SetAttributes(fileHandle.Path, isHidden, isReadonly, isArchived); } catch (Exception ex) { NTStatus status = ToNTStatus(ex); Log(Severity.Verbose, "SetFileInformation: Failed to set file attributes on '{0}'. {1}.", fileHandle.Path, status); return(status); } try { m_fileSystem.SetDates(fileHandle.Path, basicInformation.CreationTime, basicInformation.LastWriteTime, basicInformation.LastAccessTime); } catch (Exception ex) { NTStatus status = ToNTStatus(ex); Log(Severity.Verbose, "SetFileInformation: Failed to set file dates on '{0}'. {1}.", fileHandle.Path, status); return(status); } return(NTStatus.STATUS_SUCCESS); } else if (information is FileRenameInformationType2) { FileRenameInformationType2 renameInformation = (FileRenameInformationType2)information; string newFileName = renameInformation.FileName; if (!newFileName.StartsWith(@"\")) { newFileName = @"\" + newFileName; } if (fileHandle.Stream != null) { fileHandle.Stream.Close(); } // Note: it's possible that we just want to upcase / downcase a filename letter. try { if (renameInformation.ReplaceIfExists && (m_fileSystem.GetEntry(newFileName) != null)) { m_fileSystem.Delete(newFileName); } m_fileSystem.Move(fileHandle.Path, newFileName); Log(Severity.Information, "SetFileInformation: Renamed '{0}' to '{1}'", fileHandle.Path, newFileName); } catch (Exception ex) { NTStatus status = ToNTStatus(ex); Log(Severity.Verbose, "SetFileInformation: Cannot rename '{0}' to '{1}'. {2}.", fileHandle.Path, newFileName, status); return(status); } fileHandle.Path = newFileName; return(NTStatus.STATUS_SUCCESS); } else if (information is FileDispositionInformation) { if (((FileDispositionInformation)information).DeletePending) { // We're supposed to delete the file on close, but it's too late to report errors at this late stage if (fileHandle.Stream != null) { fileHandle.Stream.Close(); } try { m_fileSystem.Delete(fileHandle.Path); Log(Severity.Information, "SetFileInformation: Deleted '{0}'", fileHandle.Path); } catch (Exception ex) { NTStatus status = ToNTStatus(ex); Log(Severity.Information, "SetFileInformation: Error deleting '{0}'. {1}.", fileHandle.Path, status); return(status); } } return(NTStatus.STATUS_SUCCESS); } else if (information is FileAllocationInformation) { long allocationSize = ((FileAllocationInformation)information).AllocationSize; try { fileHandle.Stream.SetLength(allocationSize); } catch (Exception ex) { NTStatus status = ToNTStatus(ex); Log(Severity.Verbose, "SetFileInformation: Cannot set allocation for '{0}'. {1}.", fileHandle.Path, status); return(status); } return(NTStatus.STATUS_SUCCESS); } else if (information is FileEndOfFileInformation) { long endOfFile = ((FileEndOfFileInformation)information).EndOfFile; try { fileHandle.Stream.SetLength(endOfFile); } catch (Exception ex) { NTStatus status = ToNTStatus(ex); Log(Severity.Verbose, "SetFileInformation: Cannot set end of file for '{0}'. {1}.", fileHandle.Path, status); return(status); } return(NTStatus.STATUS_SUCCESS); } else { return(NTStatus.STATUS_NOT_IMPLEMENTED); } }
public NTStatus CreateFile(out object handle, out FileStatus fileStatus, string path, AccessMask desiredAccess, FileAttributes fileAttributes, ShareAccess shareAccess, CreateDisposition createDisposition, CreateOptions createOptions, SecurityContext securityContext) { handle = null; fileStatus = FileStatus.FILE_DOES_NOT_EXIST; FileAccess createAccess = NTFileStoreHelper.ToCreateFileAccess(desiredAccess, createDisposition); bool requestedWriteAccess = (createAccess & FileAccess.Write) > 0; bool forceDirectory = (createOptions & CreateOptions.FILE_DIRECTORY_FILE) > 0; bool forceFile = (createOptions & CreateOptions.FILE_NON_DIRECTORY_FILE) > 0; if (forceDirectory & (createDisposition != CreateDisposition.FILE_CREATE && createDisposition != CreateDisposition.FILE_OPEN && createDisposition != CreateDisposition.FILE_OPEN_IF && createDisposition != CreateDisposition.FILE_SUPERSEDE)) { return(NTStatus.STATUS_INVALID_PARAMETER); } // Windows will try to access named streams (alternate data streams) regardless of the FILE_NAMED_STREAMS flag, we need to prevent this behaviour. if (path.Contains(":")) { // Windows Server 2003 will return STATUS_OBJECT_NAME_NOT_FOUND return(NTStatus.STATUS_NO_SUCH_FILE); } FileSystemEntry entry; try { entry = m_fileSystem.GetEntry(path); } catch (Exception ex) { NTStatus status = ToNTStatus(ex); Log(Severity.Verbose, "CreateFile: Error retrieving '{0}'. {1}.", path, status); return(status); } if (createDisposition == CreateDisposition.FILE_OPEN) { if (entry == null) { return(NTStatus.STATUS_NO_SUCH_FILE); } fileStatus = FileStatus.FILE_EXISTS; if (entry.IsDirectory && forceFile) { return(NTStatus.STATUS_FILE_IS_A_DIRECTORY); } if (!entry.IsDirectory && forceDirectory) { return(NTStatus.STATUS_OBJECT_PATH_INVALID); } } else if (createDisposition == CreateDisposition.FILE_CREATE) { if (entry != null) { // File already exists, fail the request Log(Severity.Verbose, "CreateFile: File '{0}' already exists.", path); fileStatus = FileStatus.FILE_EXISTS; return(NTStatus.STATUS_OBJECT_NAME_COLLISION); } if (!requestedWriteAccess) { return(NTStatus.STATUS_ACCESS_DENIED); } try { if (forceDirectory) { Log(Severity.Information, "CreateFile: Creating directory '{0}'", path); entry = m_fileSystem.CreateDirectory(path); } else { Log(Severity.Information, "CreateFile: Creating file '{0}'", path); entry = m_fileSystem.CreateFile(path); } } catch (Exception ex) { NTStatus status = ToNTStatus(ex); Log(Severity.Verbose, "CreateFile: Error creating '{0}'. {1}.", path, status); return(status); } fileStatus = FileStatus.FILE_CREATED; } else if (createDisposition == CreateDisposition.FILE_OPEN_IF || createDisposition == CreateDisposition.FILE_OVERWRITE || createDisposition == CreateDisposition.FILE_OVERWRITE_IF || createDisposition == CreateDisposition.FILE_SUPERSEDE) { if (entry == null) { if (createDisposition == CreateDisposition.FILE_OVERWRITE) { return(NTStatus.STATUS_OBJECT_PATH_NOT_FOUND); } if (!requestedWriteAccess) { return(NTStatus.STATUS_ACCESS_DENIED); } try { if (forceDirectory) { Log(Severity.Information, "CreateFile: Creating directory '{0}'", path); entry = m_fileSystem.CreateDirectory(path); } else { Log(Severity.Information, "CreateFile: Creating file '{0}'", path); entry = m_fileSystem.CreateFile(path); } } catch (Exception ex) { NTStatus status = ToNTStatus(ex); Log(Severity.Verbose, "CreateFile: Error creating '{0}'. {1}.", path, status); return(status); } fileStatus = FileStatus.FILE_CREATED; } else { fileStatus = FileStatus.FILE_EXISTS; if (createDisposition == CreateDisposition.FILE_OPEN_IF) { if (entry.IsDirectory && forceFile) { return(NTStatus.STATUS_FILE_IS_A_DIRECTORY); } if (!entry.IsDirectory && forceDirectory) { return(NTStatus.STATUS_OBJECT_PATH_INVALID); } } else { if (!requestedWriteAccess) { return(NTStatus.STATUS_ACCESS_DENIED); } if (createDisposition == CreateDisposition.FILE_OVERWRITE || createDisposition == CreateDisposition.FILE_OVERWRITE_IF) { // Truncate the file try { Stream temp = m_fileSystem.OpenFile(path, FileMode.Truncate, FileAccess.ReadWrite, FileShare.ReadWrite, FileOptions.None); temp.Close(); } catch (Exception ex) { NTStatus status = ToNTStatus(ex); Log(Severity.Verbose, "CreateFile: Error truncating '{0}'. {1}.", path, status); return(status); } fileStatus = FileStatus.FILE_OVERWRITTEN; } else if (createDisposition == CreateDisposition.FILE_SUPERSEDE) { // Delete the old file try { m_fileSystem.Delete(path); } catch (Exception ex) { NTStatus status = ToNTStatus(ex); Log(Severity.Verbose, "CreateFile: Error deleting '{0}'. {1}.", path, status); return(status); } try { if (forceDirectory) { Log(Severity.Information, "CreateFile: Creating directory '{0}'", path); entry = m_fileSystem.CreateDirectory(path); } else { Log(Severity.Information, "CreateFile: Creating file '{0}'", path); entry = m_fileSystem.CreateFile(path); } } catch (Exception ex) { NTStatus status = ToNTStatus(ex); Log(Severity.Verbose, "CreateFile: Error creating '{0}'. {1}.", path, status); return(status); } fileStatus = FileStatus.FILE_SUPERSEDED; } } } } else { return(NTStatus.STATUS_INVALID_PARAMETER); } FileAccess fileAccess = NTFileStoreHelper.ToFileAccess(desiredAccess); Stream stream; if (fileAccess == (FileAccess)0 || entry.IsDirectory) { stream = null; } else { // Note that SetFileInformationByHandle/FILE_DISPOSITION_INFO has no effect if the handle was opened with FILE_DELETE_ON_CLOSE. NTStatus openStatus = OpenFileStream(out stream, path, fileAccess, shareAccess, createOptions); if (openStatus != NTStatus.STATUS_SUCCESS) { return(openStatus); } } bool deleteOnClose = (createOptions & CreateOptions.FILE_DELETE_ON_CLOSE) > 0; handle = new FileHandle(path, entry.IsDirectory, stream, deleteOnClose); if (fileStatus != FileStatus.FILE_CREATED && fileStatus != FileStatus.FILE_OVERWRITTEN && fileStatus != FileStatus.FILE_SUPERSEDED) { fileStatus = FileStatus.FILE_OPENED; } return(NTStatus.STATUS_SUCCESS); }