public NTStatus CreateFile(out object handle, out FileStatus fileStatus, string path, AccessMask desiredAccess, 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 exist", 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 (!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); 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.File); Stream stream; bool deleteOnClose = false; if (fileAccess == (FileAccess)0 || entry.IsDirectory) { stream = null; } else { NTStatus openStatus = OpenFileStream(out stream, path, fileAccess, shareAccess, createOptions); if (openStatus != NTStatus.STATUS_SUCCESS) { return(openStatus); } } 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); }
public FileAccessInformation(byte[] buffer, int offset) { AccessFlags = (AccessMask)LittleEndianConverter.ToUInt32(buffer, offset + 0); }
/// <summary> /// Will return desired FileAccess rights to the file data. /// </summary> public static FileAccess ToFileAccess(AccessMask desiredAccess) { return(ToFileAccess((FileAccessMask)desiredAccess)); }
public Task <(NTStatus status, object handle, FileStatus fileStatus)> CreateFile(string path, AccessMask desiredAccess, FileAttributes fileAttributes, ShareAccess shareAccess, CreateDisposition createDisposition, CreateOptions createOptions, SecurityContext securityContext, CancellationToken cancellationToken) { var 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); var handle = new FileHandle(path, false, stream, false); fileStatus = FileStatus.FILE_OPENED; return(Task.FromResult <(NTStatus, object, FileStatus)>((NTStatus.STATUS_SUCCESS, handle, fileStatus))); } return(Task.FromResult <(NTStatus, object, FileStatus)>((NTStatus.STATUS_OBJECT_PATH_NOT_FOUND, null, fileStatus))); }
public AccessAllowedACE(byte[] buffer, int offset) { Header = new AceHeader(buffer, offset + 0); Mask = (AccessMask)LittleEndianConverter.ToUInt32(buffer, offset + 4); Sid = new SID(buffer, offset + 8); }