Exemple #1
0
        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);
        }
Exemple #2
0
        /// <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);
            }
        }
Exemple #4
0
        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);
            }
        }
Exemple #5
0
        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);
        }