123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- using System;
- using System.Collections.Generic;
- using System.IO;
- using SMBLibrary.SMB2;
- using Utilities;
- namespace SMBLibrary.Server.SMB2
- {
- internal class LockHelper
- {
- internal static SMB2Command GetLockResponse(LockRequest request, ISMBShare share, SMB2ConnectionState state)
- {
- SMB2Session session = state.GetSession(request.Header.SessionID);
- OpenFileObject openFile = session.GetOpenFileObject(request.FileId);
- if (openFile == null)
- {
- state.LogToServer(Severity.Verbose, "Lock failed. Invalid FileId. (SessionID: {0}, TreeID: {1}, FileId: {2})", request.Header.SessionID, request.Header.TreeID, request.FileId.Volatile);
- return new ErrorResponse(request.CommandName, NTStatus.STATUS_FILE_CLOSED);
- }
- if (request.Locks.Count == 0)
- {
-
- state.LogToServer(Severity.Verbose, "Lock: Invalid number of locks, must be greater than 0.");
- return new ErrorResponse(request.CommandName, NTStatus.STATUS_INVALID_PARAMETER);
- }
-
-
-
- bool unlock = request.Locks[0].Unlock;
- foreach(LockElement lockElement in request.Locks)
- {
- if (unlock)
- {
- if (lockElement.SharedLock || lockElement.ExclusiveLock)
- {
- state.LogToServer(Severity.Verbose, "Lock: Invalid parameter: Lock in a series of unlocks.");
- return new ErrorResponse(request.CommandName, NTStatus.STATUS_INVALID_PARAMETER);
- }
- }
- else
- {
- if (lockElement.Unlock)
- {
- state.LogToServer(Severity.Verbose, "Lock: Invalid parameter: Unlock in a series of locks.");
- return new ErrorResponse(request.CommandName, NTStatus.STATUS_INVALID_PARAMETER);
- }
- if (lockElement.SharedLock && lockElement.ExclusiveLock)
- {
- state.LogToServer(Severity.Verbose, "Lock: Invalid parameter: SMB2_LOCKFLAG_SHARED_LOCK and SMB2_LOCKFLAG_EXCLUSIVE_LOCK are mutually exclusive.");
- return new ErrorResponse(request.CommandName, NTStatus.STATUS_INVALID_PARAMETER);
- }
- if (request.Locks.Count > 1 && !lockElement.FailImmediately)
- {
- state.LogToServer(Severity.Verbose, "Lock: Invalid parameter: SMB2_LOCKFLAG_FAIL_IMMEDIATELY not set in a series of locks.");
- return new ErrorResponse(request.CommandName, NTStatus.STATUS_INVALID_PARAMETER);
- }
- }
- }
-
- for(int lockIndex = 0; lockIndex < request.Locks.Count; lockIndex++)
- {
- LockElement lockElement = request.Locks[lockIndex];
- if (unlock)
- {
- NTStatus status = share.FileStore.UnlockFile(openFile.Handle, (long)lockElement.Offset, (long)lockElement.Length);
- if (status != NTStatus.STATUS_SUCCESS)
- {
-
- state.LogToServer(Severity.Information, "Lock: Unlocking '{0}{1}' failed. Offset: {2}, Length: {3}. NTStatus: {4}.", share.Name, openFile.Path, lockElement.Offset, lockElement.Length, status);
- return new ErrorResponse(request.CommandName, status);
- }
- state.LogToServer(Severity.Information, "Lock: Unlocking '{0}{1}' succeeded. Offset: {2}, Length: {3}.", share.Name, openFile.Path, lockElement.Offset, lockElement.Length);
- }
- else
- {
- NTStatus status = share.FileStore.LockFile(openFile.Handle, (long)lockElement.Offset, (long)lockElement.Length, lockElement.ExclusiveLock);
- if (status != NTStatus.STATUS_SUCCESS)
- {
-
- state.LogToServer(Severity.Information, "Lock: Locking '{0}{1}' failed. Offset: {2}, Length: {3}. NTStatus: {4}.", share.Name, openFile.Path, lockElement.Offset, lockElement.Length, status);
- for (int index = 0; index < lockIndex; index++)
- {
- share.FileStore.UnlockFile(openFile.Handle, (long)request.Locks[index].Offset, (long)request.Locks[index].Length);
- }
- return new ErrorResponse(request.CommandName, status);
- }
- state.LogToServer(Severity.Information, "Lock: Locking '{0}{1}' succeeded. Offset: {2}, Length: {3}.", share.Name, openFile.Path, lockElement.Offset, lockElement.Length);
- }
- }
- return new LockResponse();
- }
- }
- }
|