Improved Transaction2Subcommands implementation

This commit is contained in:
Tal Aloni 2017-01-07 23:56:26 +02:00
parent 2f4a6e1538
commit 8864c4f335
10 changed files with 106 additions and 86 deletions

View file

@ -24,7 +24,7 @@ namespace SMBLibrary.SMB1
}
public Transaction2CreateDirectoryResponse(byte[] parameters, byte[] data, QueryInformationLevel informationLevel, bool isUnicode) : base()
public Transaction2CreateDirectoryResponse(byte[] parameters, byte[] data, bool isUnicode) : base()
{
EaErrorOffset = LittleEndianConverter.ToUInt16(parameters, 0);
}

View file

@ -24,7 +24,7 @@ namespace SMBLibrary.SMB1
public SearchStorageType SearchStorageType;
public string FileName; // SMB_STRING
// Data:
FullExtendedAttributeList GetExtendedAttributeList; // Used with FindInformationLevel.SMB_INFO_QUERY_EAS_FROM_LIST
public FullExtendedAttributeList GetExtendedAttributeList; // Used with FindInformationLevel.SMB_INFO_QUERY_EAS_FROM_LIST
public Transaction2FindFirst2Request() : base()
{

View file

@ -19,19 +19,18 @@ namespace SMBLibrary.SMB1
public const int ParametersLength = 10;
// Parameters:
public ushort SID; // Search handle
public ushort SearchCount;
private ushort SearchCount;
public bool EndOfSearch;
public ushort EaErrorOffset;
public ushort LastNameOffset;
// Data:
public FindInformationList FindInfoList;
private byte[] FindInformationListBytes = new byte[0];
public Transaction2FindFirst2Response() : base()
{
FindInfoList = new FindInformationList();
}
public Transaction2FindFirst2Response(byte[] parameters, byte[] data, FindInformationLevel informationLevel, bool isUnicode, bool returnResumeKeys) : base()
public Transaction2FindFirst2Response(byte[] parameters, byte[] data, bool isUnicode) : base()
{
SID = LittleEndianConverter.ToUInt16(parameters, 0);
SearchCount = LittleEndianConverter.ToUInt16(parameters, 2);
@ -39,13 +38,11 @@ namespace SMBLibrary.SMB1
EaErrorOffset = LittleEndianConverter.ToUInt16(parameters, 6);
LastNameOffset = LittleEndianConverter.ToUInt16(parameters, 8);
FindInfoList = new FindInformationList(data, informationLevel, isUnicode, returnResumeKeys);
FindInformationListBytes = data;
}
public override byte[] GetParameters(bool isUnicode)
{
SearchCount = (ushort)FindInfoList.Count;
byte[] parameters = new byte[ParametersLength];
LittleEndianWriter.WriteUInt16(parameters, 0, SID);
LittleEndianWriter.WriteUInt16(parameters, 2, SearchCount);
@ -57,7 +54,18 @@ namespace SMBLibrary.SMB1
public override byte[] GetData(bool isUnicode)
{
return FindInfoList.GetBytes(isUnicode);
return FindInformationListBytes;
}
public FindInformationList GetFindInformationList(FindInformationLevel findInformationLevel, bool isUnicode, bool returnResumeKeys)
{
return new FindInformationList(FindInformationListBytes, findInformationLevel, isUnicode, returnResumeKeys);
}
public void SetFindInformationList(FindInformationList findInformationList, bool isUnicode)
{
SearchCount = (ushort)findInformationList.Count;
FindInformationListBytes = findInformationList.GetBytes(isUnicode);
}
public override Transaction2SubcommandName SubcommandName

View file

@ -18,26 +18,25 @@ namespace SMBLibrary.SMB1
{
public const int ParametersLength = 8;
// Parameters:
public ushort SearchCount;
private ushort SearchCount;
public bool EndOfSearch;
public ushort EaErrorOffset;
public ushort LastNameOffset;
// Data:
public FindInformationList FindInfoList;
private byte[] FindInformationListBytes = new byte[0];
public Transaction2FindNext2Response() : base()
{
FindInfoList = new FindInformationList();
}
public Transaction2FindNext2Response(byte[] parameters, byte[] data, FindInformationLevel informationLevel, bool isUnicode, bool returnResumeKeys) : base()
public Transaction2FindNext2Response(byte[] parameters, byte[] data, bool isUnicode) : base()
{
SearchCount = LittleEndianConverter.ToUInt16(parameters, 0);
EndOfSearch = LittleEndianConverter.ToUInt16(parameters, 2) != 0;
EaErrorOffset = LittleEndianConverter.ToUInt16(parameters, 4);
LastNameOffset = LittleEndianConverter.ToUInt16(parameters, 6);
FindInfoList = new FindInformationList(data, informationLevel, isUnicode, returnResumeKeys);
FindInformationListBytes = data;
}
public override byte[] GetParameters(bool isUnicode)
@ -52,7 +51,18 @@ namespace SMBLibrary.SMB1
public override byte[] GetData(bool isUnicode)
{
return FindInfoList.GetBytes(isUnicode);
return FindInformationListBytes;
}
public FindInformationList GetFindInformationList(FindInformationLevel findInformationLevel, bool isUnicode, bool returnResumeKeys)
{
return new FindInformationList(FindInformationListBytes, findInformationLevel, isUnicode, returnResumeKeys);
}
public void SetFindInformationList(FindInformationList findInformationList, bool isUnicode)
{
SearchCount = (ushort)findInformationList.Count;
FindInformationListBytes = findInformationList.GetBytes(isUnicode);
}
public override Transaction2SubcommandName SubcommandName

View file

@ -17,21 +17,31 @@ namespace SMBLibrary.SMB1
public class Transaction2QueryFSInformationResponse : Transaction2Subcommand
{
// Data:
public QueryFSInformation QueryFSInfo;
private byte[] QueryFSInformationBytes;
public Transaction2QueryFSInformationResponse() : base()
{
}
public Transaction2QueryFSInformationResponse(byte[] parameters, byte[] data, QueryFSInformationLevel informationLevel, bool isUnicode) : base()
public Transaction2QueryFSInformationResponse(byte[] parameters, byte[] data, bool isUnicode) : base()
{
QueryFSInfo = QueryFSInformation.GetQueryFSInformation(data, informationLevel, isUnicode);
QueryFSInformationBytes = data;
}
public override byte[] GetData(bool isUnicode)
{
return QueryFSInfo.GetBytes(isUnicode);
return QueryFSInformationBytes;
}
public QueryFSInformation GetQueryFSInformation(QueryFSInformationLevel informationLevel, bool isUnicode)
{
return QueryFSInformation.GetQueryFSInformation(QueryFSInformationBytes, informationLevel, isUnicode);
}
public void SetQueryFSInformation(QueryFSInformation queryFSInformation, bool isUnicode)
{
QueryFSInformationBytes = queryFSInformation.GetBytes(isUnicode);
}
public override Transaction2SubcommandName SubcommandName

View file

@ -17,46 +17,39 @@ namespace SMBLibrary.SMB1
public class Transaction2QueryFileInformationResponse : Transaction2Subcommand
{
// Parameters:
public ushort EaErrorOffset;
public ushort EaErrorOffset; // Meaningful only when request's InformationLevel is SMB_INFO_QUERY_EAS_FROM_LIST
// Data:
public QueryInformation QueryInfo;
private byte[] QueryInformationBytes = new byte[0];
public Transaction2QueryFileInformationResponse() : base()
{
}
public Transaction2QueryFileInformationResponse(byte[] parameters, byte[] data, QueryInformationLevel informationLevel, bool isUnicode) : base()
{
if ((ushort)informationLevel > 0x0100)
public Transaction2QueryFileInformationResponse(byte[] parameters, byte[] data, bool isUnicode) : base()
{
EaErrorOffset = LittleEndianConverter.ToUInt16(parameters, 0);
}
QueryInfo = QueryInformation.GetQueryInformation(data, informationLevel);
QueryInformationBytes = data;
}
public override byte[] GetParameters(bool isUnicode)
{
if ((ushort)QueryInfo.InformationLevel > 0x0100)
{
byte[] parameters = new byte[2];
LittleEndianWriter.WriteUInt16(parameters, 0, EaErrorOffset);
return parameters;
}
return new byte[0];
return LittleEndianConverter.GetBytes(EaErrorOffset);
}
public override byte[] GetData(bool isUnicode)
{
if (QueryInfo == null)
{
// SMB_INFO_IS_NAME_VALID
return new byte[0];
return QueryInformationBytes;
}
else
public QueryInformation GetQueryInformation(QueryInformationLevel queryInformationLevel)
{
return QueryInfo.GetBytes();
return QueryInformation.GetQueryInformation(QueryInformationBytes, queryInformationLevel);
}
public void SetQueryInformation(QueryInformation queryInformation)
{
QueryInformationBytes = queryInformation.GetBytes();
}
public override Transaction2SubcommandName SubcommandName

View file

@ -17,46 +17,39 @@ namespace SMBLibrary.SMB1
public class Transaction2QueryPathInformationResponse : Transaction2Subcommand
{
// Parameters:
public ushort EaErrorOffset;
public ushort EaErrorOffset; // Meaningful only when request's InformationLevel is SMB_INFO_QUERY_EAS_FROM_LIST
// Data:
public QueryInformation QueryInfo;
private byte[] QueryInformationBytes;
public Transaction2QueryPathInformationResponse() : base()
{
}
public Transaction2QueryPathInformationResponse(byte[] parameters, byte[] data, QueryInformationLevel informationLevel, bool isUnicode) : base()
{
if ((ushort)informationLevel > 0x0100)
public Transaction2QueryPathInformationResponse(byte[] parameters, byte[] data, bool isUnicode) : base()
{
EaErrorOffset = LittleEndianConverter.ToUInt16(parameters, 0);
}
QueryInfo = QueryInformation.GetQueryInformation(data, informationLevel);
QueryInformationBytes = data;
}
public override byte[] GetParameters(bool isUnicode)
{
if ((ushort)QueryInfo.InformationLevel > 0x0100)
{
byte[] parameters = new byte[2];
LittleEndianWriter.WriteUInt16(parameters, 0, EaErrorOffset);
return parameters;
}
return new byte[0];
return LittleEndianConverter.GetBytes(EaErrorOffset);
}
public override byte[] GetData(bool isUnicode)
{
if (QueryInfo == null)
{
// SMB_INFO_IS_NAME_VALID
return new byte[0];
return QueryInformationBytes;
}
else
public QueryInformation GetQueryInformation(QueryInformationLevel queryInformationLevel)
{
return QueryInfo.GetBytes();
return QueryInformation.GetQueryInformation(QueryInformationBytes, queryInformationLevel);
}
public void SetQueryInformation(QueryInformation queryInformation)
{
QueryInformationBytes = queryInformation.GetBytes();
}
public override Transaction2SubcommandName SubcommandName

View file

@ -17,14 +17,14 @@ namespace SMBLibrary.SMB1
public class Transaction2SetFileInformationResponse : Transaction2Subcommand
{
// Parameters:
public ushort EaErrorOffset;
public ushort EaErrorOffset; // Meaningful only when the request's InformationLevel is set to SMB_INFO_SET_EAS
public Transaction2SetFileInformationResponse() : base()
{
}
public Transaction2SetFileInformationResponse(byte[] parameters, byte[] data, QueryInformationLevel informationLevel, bool isUnicode) : base()
public Transaction2SetFileInformationResponse(byte[] parameters, byte[] data, bool isUnicode) : base()
{
EaErrorOffset = LittleEndianConverter.ToUInt16(parameters, 0);
}

View file

@ -17,14 +17,14 @@ namespace SMBLibrary.SMB1
public class Transaction2SetPathInformationResponse : Transaction2Subcommand
{
// Parameters:
public ushort EaErrorOffset;
public ushort EaErrorOffset; // Meaningful only when the request's InformationLevel is set to SMB_INFO_SET_EAS
public Transaction2SetPathInformationResponse() : base()
{
}
public Transaction2SetPathInformationResponse(byte[] parameters, byte[] data, QueryInformationLevel informationLevel, bool isUnicode) : base()
public Transaction2SetPathInformationResponse(byte[] parameters, byte[] data, bool isUnicode) : base()
{
EaErrorOffset = LittleEndianConverter.ToUInt16(parameters, 0);
}

View file

@ -101,18 +101,20 @@ namespace SMBLibrary.Server
bool returnResumeKeys = (subcommand.Flags & FindFlags.SMB_FIND_RETURN_RESUME_KEYS) > 0;
int entriesToReturn = Math.Min(subcommand.SearchCount, entries.Count);
// We ignore SearchAttributes
Transaction2FindFirst2Response response = new Transaction2FindFirst2Response();
FindInformationList findInformationList = new FindInformationList();
for (int index = 0; index < entriesToReturn; index++)
{
FindInformation infoEntry = InfoHelper.FromFileSystemEntry(entries[index], subcommand.InformationLevel, header.UnicodeFlag, returnResumeKeys);
response.FindInfoList.Add(infoEntry);
if (response.FindInfoList.GetLength(header.UnicodeFlag) > state.GetMaxDataCount(header.PID))
findInformationList.Add(infoEntry);
if (findInformationList.GetLength(header.UnicodeFlag) > state.GetMaxDataCount(header.PID))
{
response.FindInfoList.RemoveAt(response.FindInfoList.Count - 1);
findInformationList.RemoveAt(findInformationList.Count - 1);
break;
}
}
int returnCount = response.FindInfoList.Count;
int returnCount = findInformationList.Count;
Transaction2FindFirst2Response response = new Transaction2FindFirst2Response();
response.SetFindInformationList(findInformationList, header.UnicodeFlag);
response.EndOfSearch = (returnCount == entries.Count) && (entries.Count <= subcommand.SearchCount);
bool closeAtEndOfSearch = (subcommand.Flags & FindFlags.SMB_FIND_CLOSE_AT_EOS) > 0;
bool closeAfterRequest = (subcommand.Flags & FindFlags.SMB_FIND_CLOSE_AFTER_REQUEST) > 0;
@ -193,7 +195,6 @@ namespace SMBLibrary.Server
internal static Transaction2FindNext2Response GetSubcommandResponse(SMBHeader header, Transaction2FindNext2Request subcommand, FileSystemShare share, StateObject state)
{
Transaction2FindNext2Response response = new Transaction2FindNext2Response();
if (!state.OpenSearches.ContainsKey(subcommand.SID))
{
header.Status = NTStatus.STATUS_INVALID_HANDLE;
@ -202,20 +203,22 @@ namespace SMBLibrary.Server
bool returnResumeKeys = (subcommand.Flags & FindFlags.SMB_FIND_RETURN_RESUME_KEYS) > 0;
List<FileSystemEntry> entries = state.OpenSearches[subcommand.SID];
FindInformationList findInformationList = new FindInformationList();
for (int index = 0; index < entries.Count; index++)
{
FindInformation infoEntry = InfoHelper.FromFileSystemEntry(entries[index], subcommand.InformationLevel, header.UnicodeFlag, returnResumeKeys);
response.FindInfoList.Add(infoEntry);
if (response.FindInfoList.GetLength(header.UnicodeFlag) > state.GetMaxDataCount(header.PID))
findInformationList.Add(infoEntry);
if (findInformationList.GetLength(header.UnicodeFlag) > state.GetMaxDataCount(header.PID))
{
response.FindInfoList.RemoveAt(response.FindInfoList.Count - 1);
findInformationList.RemoveAt(findInformationList.Count - 1);
break;
}
}
int returnCount = response.FindInfoList.Count;
int returnCount = findInformationList.Count;
Transaction2FindNext2Response response = new Transaction2FindNext2Response();
response.SetFindInformationList(findInformationList, header.UnicodeFlag);
entries.RemoveRange(0, returnCount);
state.OpenSearches[subcommand.SID] = entries;
response.SearchCount = (ushort)returnCount;
response.EndOfSearch = (returnCount == entries.Count) && (entries.Count <= subcommand.SearchCount);
if (response.EndOfSearch)
{
@ -227,7 +230,8 @@ namespace SMBLibrary.Server
internal static Transaction2QueryFSInformationResponse GetSubcommandResponse(SMBHeader header, Transaction2QueryFSInformationRequest subcommand, FileSystemShare share)
{
Transaction2QueryFSInformationResponse response = new Transaction2QueryFSInformationResponse();
response.QueryFSInfo = InfoHelper.GetFSInformation(subcommand.InformationLevel, share.FileSystem);
QueryFSInformation queryFSInformation = InfoHelper.GetFSInformation(subcommand.InformationLevel, share.FileSystem);
response.SetQueryFSInformation(queryFSInformation, header.UnicodeFlag);
return response;
}
@ -245,7 +249,8 @@ namespace SMBLibrary.Server
return null;
}
Transaction2QueryPathInformationResponse response = new Transaction2QueryPathInformationResponse();
response.QueryInfo = InfoHelper.FromFileSystemEntry(entry, subcommand.InformationLevel);
QueryInformation queryInformation = InfoHelper.FromFileSystemEntry(entry, subcommand.InformationLevel);
response.SetQueryInformation(queryInformation);
return response;
}
@ -267,7 +272,8 @@ namespace SMBLibrary.Server
return null;
}
Transaction2QueryFileInformationResponse response = new Transaction2QueryFileInformationResponse();
response.QueryInfo = InfoHelper.FromFileSystemEntry(entry, subcommand.InformationLevel);
QueryInformation queryInformation = InfoHelper.FromFileSystemEntry(entry, subcommand.InformationLevel);
response.SetQueryInformation(queryInformation);
return response;
}