Esempio n. 1
0
        internal static SMBCommand GetCreateDirectoryResponse(SMBHeader header, CreateDirectoryRequest request, FileSystemShare share, StateObject state)
        {
            string userName = state.GetConnectedUserName(header.UID);

            if (!share.HasWriteAccess(userName))
            {
                header.Status = NTStatus.STATUS_ACCESS_DENIED;
                return(new ErrorResponse(CommandName.SMB_COM_CREATE_DIRECTORY));
            }
            IFileSystem fileSystem = share.FileSystem;

            try
            {
                fileSystem.CreateDirectory(request.DirectoryName);
            }
            catch (IOException)
            {
                header.Status = NTStatus.STATUS_OBJECT_NAME_INVALID;
                return(new ErrorResponse(CommandName.SMB_COM_CREATE_DIRECTORY));
            }
            catch (UnauthorizedAccessException)
            {
                header.Status = NTStatus.STATUS_ACCESS_DENIED;
                return(new ErrorResponse(CommandName.SMB_COM_CREATE_DIRECTORY));
            }

            return(new CreateDirectoryResponse());
        }
Esempio n. 2
0
        internal static SMBCommand GetRenameResponse(SMBHeader header, RenameRequest request, FileSystemShare share, StateObject state)
        {
            string userName = state.GetConnectedUserName(header.UID);

            if (!share.HasWriteAccess(userName))
            {
                header.Status = NTStatus.STATUS_ACCESS_DENIED;
                return(new ErrorResponse(CommandName.SMB_COM_RENAME));
            }
            IFileSystem fileSystem = share.FileSystem;

            FileSystemEntry sourceEntry = fileSystem.GetEntry(request.OldFileName);

            if (sourceEntry == null)
            {
                header.Status = NTStatus.STATUS_NO_SUCH_FILE;
                return(new ErrorResponse(CommandName.SMB_COM_RENAME));
            }

            // The file must not already exist unless we just want to upcase / downcase a filename letter
            FileSystemEntry destinationEntry = fileSystem.GetEntry(request.NewFileName);

            if (destinationEntry != null &&
                !String.Equals(request.OldFileName, request.NewFileName, StringComparison.InvariantCultureIgnoreCase))
            {
                // The new file already exists.
                header.Status = NTStatus.STATUS_OBJECT_NAME_COLLISION;
                return(new ErrorResponse(CommandName.SMB_COM_RENAME));
            }

            try
            {
                fileSystem.Move(request.OldFileName, request.NewFileName);
                return(new RenameResponse());
            }
            catch (IOException)
            {
                header.Status = NTStatus.STATUS_SHARING_VIOLATION;
                return(new ErrorResponse(CommandName.SMB_COM_RENAME));
            }
            catch (UnauthorizedAccessException)
            {
                header.Status = NTStatus.STATUS_ACCESS_DENIED;
                return(new ErrorResponse(CommandName.SMB_COM_RENAME));
            }
        }
Esempio n. 3
0
        internal static SMBCommand GetSetInformationResponse(SMBHeader header, SetInformationRequest request, FileSystemShare share, StateObject state)
        {
            string userName = state.GetConnectedUserName(header.UID);

            if (!share.HasWriteAccess(userName))
            {
                header.Status = NTStatus.STATUS_ACCESS_DENIED;
                return(new ErrorResponse(CommandName.SMB_COM_SET_INFORMATION2));
            }
            IFileSystem fileSystem = share.FileSystem;

            FileSystemEntry entry = fileSystem.GetEntry(request.FileName);

            if (entry == null)
            {
                header.Status = NTStatus.STATUS_NO_SUCH_FILE;
                return(new ErrorResponse(CommandName.SMB_COM_SET_INFORMATION));
            }

            bool?isHidden   = null;
            bool?isReadOnly = null;
            bool?isArchived = null;

            if ((request.FileAttributes & SMBLibrary.SMB1.FileAttributes.Hidden) > 0)
            {
                isHidden = true;
            }
            if ((request.FileAttributes & SMBLibrary.SMB1.FileAttributes.ReadOnly) > 0)
            {
                isReadOnly = true;
            }
            if ((request.FileAttributes & SMBLibrary.SMB1.FileAttributes.Archive) > 0)
            {
                isArchived = true;
            }
            fileSystem.SetAttributes(request.FileName, isHidden, isReadOnly, isArchived);

            if (request.LastWriteTime != SMBHelper.UTimeNotSpecified)
            {
                fileSystem.SetDates(request.FileName, null, request.LastWriteTime, null);
            }

            return(new SetInformationResponse());
        }
Esempio n. 4
0
        internal static SMBCommand GetDeleteResponse(SMBHeader header, DeleteRequest request, FileSystemShare share, StateObject state)
        {
            string userName = state.GetConnectedUserName(header.UID);

            if (!share.HasWriteAccess(userName))
            {
                header.Status = NTStatus.STATUS_ACCESS_DENIED;
                return(new ErrorResponse(CommandName.SMB_COM_DELETE));
            }
            IFileSystem fileSystem = share.FileSystem;

            FileSystemEntry entry = fileSystem.GetEntry(request.FileName);

            if (entry == null)
            {
                header.Status = NTStatus.STATUS_NO_SUCH_FILE;
                return(new ErrorResponse(CommandName.SMB_COM_DELETE));
            }

            if (!entry.IsDirectory && (request.SearchAttributes & SMBLibrary.SMB1.FileAttributes.Directory) > 0 ||
                entry.IsDirectory && (request.SearchAttributes & SMBLibrary.SMB1.FileAttributes.Directory) == 0)
            {
                header.Status = NTStatus.STATUS_OBJECT_PATH_INVALID;
                return(new ErrorResponse(CommandName.SMB_COM_DELETE));
            }

            try
            {
                fileSystem.Delete(request.FileName);
                return(new DeleteResponse());
            }
            catch (IOException)
            {
                header.Status = NTStatus.STATUS_CANNOT_DELETE;
                return(new ErrorResponse(CommandName.SMB_COM_DELETE));
            }
            catch (UnauthorizedAccessException)
            {
                header.Status = NTStatus.STATUS_ACCESS_DENIED;
                return(new ErrorResponse(CommandName.SMB_COM_DELETE));
            }
        }
Esempio n. 5
0
        internal static SMBCommand GetSetInformation2Response(SMBHeader header, SetInformation2Request request, FileSystemShare share, StateObject state)
        {
            string openedFilePath = state.GetOpenedFilePath(request.FID);

            if (openedFilePath == null)
            {
                header.Status = NTStatus.STATUS_SMB_BAD_FID;
                return(new ErrorResponse(CommandName.SMB_COM_SET_INFORMATION2));
            }

            string userName = state.GetConnectedUserName(header.UID);

            if (!share.HasWriteAccess(userName))
            {
                header.Status = NTStatus.STATUS_ACCESS_DENIED;
                return(new ErrorResponse(CommandName.SMB_COM_SET_INFORMATION2));
            }
            IFileSystem fileSystem = share.FileSystem;

            fileSystem.SetDates(openedFilePath, request.CreationDateTime, request.LastWriteDateTime, request.LastAccessDateTime);
            return(new SetInformation2Response());
        }
        internal static Transaction2SetFileInformationResponse GetSubcommandResponse(SMBHeader header, Transaction2SetFileInformationRequest subcommand, FileSystemShare share, StateObject state)
        {
            string openedFilePath = state.GetOpenedFilePath(subcommand.FID);

            if (openedFilePath == null)
            {
                header.Status = NTStatus.STATUS_INVALID_HANDLE;
                return(null);
            }

            Transaction2SetFileInformationResponse response = new Transaction2SetFileInformationResponse();

            switch (subcommand.InformationLevel)
            {
            case SetInformationLevel.SMB_INFO_STANDARD:
            {
                return(response);
            }

            case SetInformationLevel.SMB_INFO_SET_EAS:
            {
                throw new NotImplementedException();
            }

            case SetInformationLevel.SMB_SET_FILE_BASIC_INFO:
            {
                string userName = state.GetConnectedUserName(header.UID);
                if (!share.HasWriteAccess(userName))
                {
                    header.Status = NTStatus.STATUS_ACCESS_DENIED;
                    return(null);
                }

                SetFileBasicInfo info       = (SetFileBasicInfo)subcommand.SetInfo;
                bool             isHidden   = (info.ExtFileAttributes & ExtendedFileAttributes.Hidden) > 0;
                bool             isReadonly = (info.ExtFileAttributes & ExtendedFileAttributes.Readonly) > 0;
                bool             isArchived = (info.ExtFileAttributes & ExtendedFileAttributes.Archive) > 0;
                try
                {
                    share.FileSystem.SetAttributes(openedFilePath, isHidden, isReadonly, isArchived);
                }
                catch (UnauthorizedAccessException)
                {
                    header.Status = NTStatus.STATUS_ACCESS_DENIED;
                    return(null);
                }

                DateTime?creationTime   = null;
                DateTime?lastWriteDT    = null;
                DateTime?lastAccessTime = null;
                if (info.CreationTime != SMBHelper.FileTimeNotSpecified)
                {
                    creationTime = info.CreationTime;
                }
                if (info.LastWriteTime != SMBHelper.FileTimeNotSpecified)
                {
                    lastWriteDT = info.LastWriteTime;
                }
                if (info.LastAccessTime != SMBHelper.FileTimeNotSpecified)
                {
                    lastAccessTime = info.LastAccessTime;
                }

                try
                {
                    share.FileSystem.SetDates(openedFilePath, creationTime, lastWriteDT, lastAccessTime);
                }
                catch (IOException ex)
                {
                    ushort errorCode = IOExceptionHelper.GetWin32ErrorCode(ex);
                    if (errorCode == (ushort)Win32Error.ERROR_SHARING_VIOLATION)
                    {
                        // Returning STATUS_SHARING_VIOLATION is undocumented but apparently valid
                        header.Status = NTStatus.STATUS_SHARING_VIOLATION;
                        return(null);
                    }
                    else
                    {
                        header.Status = NTStatus.STATUS_DATA_ERROR;
                        return(null);
                    }
                }
                catch (UnauthorizedAccessException)
                {
                    header.Status = NTStatus.STATUS_ACCESS_DENIED;
                    return(null);
                }
                return(response);
            }

            case SetInformationLevel.SMB_SET_FILE_DISPOSITION_INFO:
            {
                if (((SetFileDispositionInfo)subcommand.SetInfo).DeletePending)
                {
                    // We're supposed to delete the file on close, but it's too late to report errors at this late stage
                    string userName = state.GetConnectedUserName(header.UID);
                    if (!share.HasWriteAccess(userName))
                    {
                        header.Status = NTStatus.STATUS_ACCESS_DENIED;
                        return(null);
                    }

                    try
                    {
                        share.FileSystem.Delete(openedFilePath);
                    }
                    catch (IOException)
                    {
                        header.Status = NTStatus.STATUS_FILE_LOCK_CONFLICT;
                        return(null);
                    }
                    catch (UnauthorizedAccessException)
                    {
                        header.Status = NTStatus.STATUS_ACCESS_DENIED;
                        return(null);
                    }
                }
                return(response);
            }

            case SetInformationLevel.SMB_SET_FILE_ALLOCATION_INFO:
            {
                // This subcommand is used to set the file length in bytes.
                // Note: the input will NOT be a multiple of the cluster size / bytes per sector.
                ulong allocationSize = ((SetFileAllocationInfo)subcommand.SetInfo).AllocationSize;
                try
                {
                    Stream stream = share.FileSystem.OpenFile(openedFilePath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
                    stream.SetLength((long)allocationSize);
                    stream.Close();
                }
                catch
                {
                }
                return(response);
            }

            case SetInformationLevel.SMB_SET_FILE_END_OF_FILE_INFO:
            {
                ulong endOfFile = ((SetFileEndOfFileInfo)subcommand.SetInfo).EndOfFile;
                try
                {
                    Stream stream = share.FileSystem.OpenFile(openedFilePath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
                    stream.SetLength((long)endOfFile);
                    stream.Close();
                }
                catch
                {
                }
                return(response);
            }

            default:
            {
                throw new InvalidRequestException();
            }
            }
        }
Esempio n. 7
0
        internal static SMBCommand GetNTCreateResponse(SMBHeader header, NTCreateAndXRequest request, object share, StateObject state)
        {
            bool   isExtended = (request.Flags & NTCreateFlags.NT_CREATE_REQUEST_EXTENDED_RESPONSE) > 0;
            string path       = request.FileName;

            if (share is NamedPipeShare)
            {
                RemoteService service = ((NamedPipeShare)share).GetService(path);
                if (service != null)
                {
                    ushort fileID = state.AddOpenedFile(path);
                    if (isExtended)
                    {
                        return(CreateResponseExtendedForNamedPipe(fileID));
                    }
                    else
                    {
                        return(CreateResponseForNamedPipe(fileID));
                    }
                }

                header.Status = NTStatus.STATUS_OBJECT_PATH_NOT_FOUND;
                return(new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX));
            }
            else // FileSystemShare
            {
                FileSystemShare fileSystemShare = (FileSystemShare)share;
                IFileSystem     fileSystem      = fileSystemShare.FileSystem;
                bool            forceDirectory  = (request.CreateOptions & CreateOptions.FILE_DIRECTORY_FILE) > 0;
                bool            forceFile       = (request.CreateOptions & CreateOptions.FILE_NON_DIRECTORY_FILE) > 0;

                if (forceDirectory & (request.CreateDisposition != CreateDisposition.FILE_CREATE &&
                                      request.CreateDisposition != CreateDisposition.FILE_OPEN &&
                                      request.CreateDisposition != CreateDisposition.FILE_OPEN_IF))
                {
                    header.Status = NTStatus.STATUS_INVALID_PARAMETER;
                    return(new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX));
                }

                // 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
                    header.Status = NTStatus.STATUS_NO_SUCH_FILE;
                    return(new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX));
                }

                FileSystemEntry entry = fileSystem.GetEntry(path);
                if (request.CreateDisposition == CreateDisposition.FILE_OPEN)
                {
                    if (entry == null)
                    {
                        header.Status = NTStatus.STATUS_OBJECT_PATH_NOT_FOUND;
                        return(new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX));
                    }

                    if (entry.IsDirectory && forceFile)
                    {
                        header.Status = NTStatus.STATUS_FILE_IS_A_DIRECTORY;
                        return(new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX));
                    }

                    if (!entry.IsDirectory && forceDirectory)
                    {
                        // Not sure if that's the correct response
                        header.Status = NTStatus.STATUS_OBJECT_NAME_COLLISION;
                        return(new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX));
                    }
                }
                else if (request.CreateDisposition == CreateDisposition.FILE_CREATE)
                {
                    if (entry != null)
                    {
                        // File already exists, fail the request
                        header.Status = NTStatus.STATUS_OBJECT_NAME_COLLISION;
                        return(new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX));
                    }

                    string userName = state.GetConnectedUserName(header.UID);
                    if (!fileSystemShare.HasWriteAccess(userName))
                    {
                        header.Status = NTStatus.STATUS_ACCESS_DENIED;
                        return(new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX));
                    }

                    try
                    {
                        if (forceDirectory)
                        {
                            entry = fileSystem.CreateDirectory(path);
                        }
                        else
                        {
                            entry = fileSystem.CreateFile(path);
                        }
                    }
                    catch (IOException ex)
                    {
                        ushort errorCode = IOExceptionHelper.GetWin32ErrorCode(ex);
                        if (errorCode == (ushort)Win32Error.ERROR_SHARING_VIOLATION)
                        {
                            header.Status = NTStatus.STATUS_SHARING_VIOLATION;
                            return(new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX));
                        }
                        else
                        {
                            header.Status = NTStatus.STATUS_DATA_ERROR;
                            return(new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX));
                        }
                    }
                    catch (UnauthorizedAccessException)
                    {
                        header.Status = NTStatus.STATUS_ACCESS_DENIED;
                        return(new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX));
                    }
                }
                else if (request.CreateDisposition == CreateDisposition.FILE_OPEN_IF ||
                         request.CreateDisposition == CreateDisposition.FILE_OVERWRITE ||
                         request.CreateDisposition == CreateDisposition.FILE_OVERWRITE_IF ||
                         request.CreateDisposition == CreateDisposition.FILE_SUPERSEDE)
                {
                    entry = fileSystem.GetEntry(path);
                    if (entry == null)
                    {
                        if (request.CreateDisposition == CreateDisposition.FILE_OVERWRITE)
                        {
                            header.Status = NTStatus.STATUS_OBJECT_PATH_NOT_FOUND;
                            return(new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX));
                        }

                        string userName = state.GetConnectedUserName(header.UID);
                        if (!fileSystemShare.HasWriteAccess(userName))
                        {
                            header.Status = NTStatus.STATUS_ACCESS_DENIED;
                            return(new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX));
                        }

                        try
                        {
                            if (forceDirectory)
                            {
                                entry = fileSystem.CreateDirectory(path);
                            }
                            else
                            {
                                entry = fileSystem.CreateFile(path);
                            }
                        }
                        catch (IOException ex)
                        {
                            ushort errorCode = IOExceptionHelper.GetWin32ErrorCode(ex);
                            if (errorCode == (ushort)Win32Error.ERROR_SHARING_VIOLATION)
                            {
                                header.Status = NTStatus.STATUS_SHARING_VIOLATION;
                                return(new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX));
                            }
                            else
                            {
                                header.Status = NTStatus.STATUS_DATA_ERROR;
                                return(new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX));
                            }
                        }
                        catch (UnauthorizedAccessException)
                        {
                            header.Status = NTStatus.STATUS_ACCESS_DENIED;
                            return(new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX));
                        }
                    }
                    else
                    {
                        if (request.CreateDisposition == CreateDisposition.FILE_OVERWRITE ||
                            request.CreateDisposition == CreateDisposition.FILE_OVERWRITE_IF ||
                            request.CreateDisposition == CreateDisposition.FILE_SUPERSEDE)
                        {
                            string userName = state.GetConnectedUserName(header.UID);
                            if (!fileSystemShare.HasWriteAccess(userName))
                            {
                                header.Status = NTStatus.STATUS_ACCESS_DENIED;
                                return(new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX));
                            }

                            // Truncate the file
                            try
                            {
                                Stream stream = fileSystem.OpenFile(path, FileMode.Truncate, FileAccess.ReadWrite, FileShare.ReadWrite);
                                stream.Close();
                            }
                            catch (IOException ex)
                            {
                                ushort errorCode = IOExceptionHelper.GetWin32ErrorCode(ex);
                                if (errorCode == (ushort)Win32Error.ERROR_SHARING_VIOLATION)
                                {
                                    header.Status = NTStatus.STATUS_SHARING_VIOLATION;
                                    return(new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX));
                                }
                                else
                                {
                                    header.Status = NTStatus.STATUS_DATA_ERROR;
                                    return(new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX));
                                }
                            }
                            catch (UnauthorizedAccessException)
                            {
                                header.Status = NTStatus.STATUS_ACCESS_DENIED;
                                return(new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX));
                            }
                        }
                    }
                }
                else
                {
                    throw new InvalidRequestException();
                }
                bool   isSequentialAccess = (request.CreateOptions & CreateOptions.FILE_SEQUENTIAL_ONLY) > 0;
                ushort fileID             = state.AddOpenedFile(path, isSequentialAccess);
                if (isExtended)
                {
                    NTCreateAndXResponseExtended response = CreateResponseExtendedFromFileSystemEntry(entry, fileID);
                    if ((request.Flags & NTCreateFlags.NT_CREATE_REQUEST_OPBATCH) > 0)
                    {
                        response.OpLockLevel = OpLockLevel.BatchOpLockGranted;
                    }
                    return(response);
                }
                else
                {
                    NTCreateAndXResponse response = CreateResponseFromFileSystemEntry(entry, fileID);
                    if ((request.Flags & NTCreateFlags.NT_CREATE_REQUEST_OPBATCH) > 0)
                    {
                        response.OpLockLevel = OpLockLevel.BatchOpLockGranted;
                    }
                    return(response);
                }
            }
        }
Esempio n. 8
0
        internal static SMBCommand GetOpenAndXResponse(SMBHeader header, OpenAndXRequest request, object share, StateObject state)
        {
            bool   isExtended = (request.Flags & OpenFlags.SMB_OPEN_EXTENDED_RESPONSE) > 0;
            string path       = request.FileName;

            if (share is NamedPipeShare)
            {
                RemoteService service = ((NamedPipeShare)share).GetService(path);
                if (service != null)
                {
                    ushort fileID = state.AddOpenedFile(path);
                    if (isExtended)
                    {
                        return(CreateResponseExtendedForNamedPipe(fileID));
                    }
                    else
                    {
                        CreateResponseForNamedPipe(fileID);
                    }
                }

                header.Status = NTStatus.STATUS_OBJECT_PATH_NOT_FOUND;
                return(new ErrorResponse(CommandName.SMB_COM_OPEN_ANDX));
            }
            else // FileSystemShare
            {
                FileSystemShare fileSystemShare = (FileSystemShare)share;
                string          userName        = state.GetConnectedUserName(header.UID);
                bool            hasWriteAccess  = fileSystemShare.HasWriteAccess(userName);
                IFileSystem     fileSystem      = fileSystemShare.FileSystem;

                OpenResult      openResult;
                FileSystemEntry entry = fileSystem.GetEntry(path);
                if (entry != null)
                {
                    if (!hasWriteAccess && request.AccessMode.AccessMode == AccessMode.Write || request.AccessMode.AccessMode == AccessMode.ReadWrite)
                    {
                        header.Status = NTStatus.STATUS_ACCESS_DENIED;
                        return(new ErrorResponse(CommandName.SMB_COM_OPEN_ANDX));
                    }

                    if (request.OpenMode.FileExistsOpts == FileExistsOpts.ReturnError)
                    {
                        header.Status = NTStatus.STATUS_OBJECT_NAME_COLLISION;
                        return(new ErrorResponse(CommandName.SMB_COM_OPEN_ANDX));
                    }
                    else if (request.OpenMode.FileExistsOpts == FileExistsOpts.TruncateToZero)
                    {
                        try
                        {
                            Stream stream = fileSystem.OpenFile(path, FileMode.Truncate, FileAccess.ReadWrite, FileShare.ReadWrite);
                            stream.Close();
                        }
                        catch (IOException ex)
                        {
                            ushort errorCode = IOExceptionHelper.GetWin32ErrorCode(ex);
                            if (errorCode == (ushort)Win32Error.ERROR_SHARING_VIOLATION)
                            {
                                header.Status = NTStatus.STATUS_SHARING_VIOLATION;
                                return(new ErrorResponse(CommandName.SMB_COM_OPEN_ANDX));
                            }
                            else
                            {
                                header.Status = NTStatus.STATUS_DATA_ERROR;
                                return(new ErrorResponse(CommandName.SMB_COM_OPEN_ANDX));
                            }
                        }
                        catch (UnauthorizedAccessException)
                        {
                            header.Status = NTStatus.STATUS_ACCESS_DENIED;
                            return(new ErrorResponse(CommandName.SMB_COM_OPEN_ANDX));
                        }
                        openResult = OpenResult.FileExistedAndWasTruncated;
                    }
                    else // FileExistsOpts.Append
                    {
                        openResult = OpenResult.FileExistedAndWasOpened;
                    }
                }
                else
                {
                    if (request.OpenMode.CreateFile == CreateFile.ReturnErrorIfNotExist)
                    {
                        header.Status = NTStatus.STATUS_NO_SUCH_FILE;
                        return(new ErrorResponse(CommandName.SMB_COM_OPEN_ANDX));
                    }

                    entry      = fileSystem.CreateFile(path);
                    openResult = OpenResult.NotExistedAndWasCreated;
                }

                ushort fileID = state.AddOpenedFile(path, true);
                if (isExtended)
                {
                    return(CreateResponseFromFileSystemEntry(entry, fileID, openResult));
                }
                else
                {
                    return(CreateResponseExtendedFromFileSystemEntry(entry, fileID, openResult));
                }
            }
        }