SMB1 command processing code refactoring

This commit is contained in:
Tal Aloni 2017-02-19 20:59:05 +02:00
parent 23f6127808
commit 4d51c7eed4
5 changed files with 104 additions and 77 deletions

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2014 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved. /* Copyright (C) 2014-2017 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
* *
* You can redistribute this program and/or modify it under the terms of * You can redistribute this program and/or modify it under the terms of
* the GNU Lesser Public License as published by the Free Software Foundation, * the GNU Lesser Public License as published by the Free Software Foundation,
@ -264,5 +264,12 @@ namespace SMBLibrary.SMB1
throw new NotImplementedException("SMB Command 0x" + ((byte)commandName).ToString("X")); throw new NotImplementedException("SMB Command 0x" + ((byte)commandName).ToString("X"));
} }
} }
public static implicit operator List<SMB1Command>(SMB1Command command)
{
List<SMB1Command> result = new List<SMB1Command>();
result.Add(command);
return result;
}
} }
} }

View file

@ -17,7 +17,7 @@ namespace SMBLibrary.Server.SMB1
/// <summary> /// <summary>
/// The client MUST send as many secondary requests as are needed to complete the transfer of the transaction request. /// The client MUST send as many secondary requests as are needed to complete the transfer of the transaction request.
/// </summary> /// </summary>
internal static SMB1Command GetNTTransactResponse(SMB1Header header, NTTransactRequest request, ISMBShare share, SMB1ConnectionState state, List<SMB1Command> sendQueue) internal static List<SMB1Command> GetNTTransactResponse(SMB1Header header, NTTransactRequest request, ISMBShare share, SMB1ConnectionState state)
{ {
if (request.TransParameters.Length < request.TotalParameterCount || if (request.TransParameters.Length < request.TotalParameterCount ||
request.TransData.Length < request.TotalDataCount) request.TransData.Length < request.TotalDataCount)
@ -37,7 +37,7 @@ namespace SMBLibrary.Server.SMB1
else else
{ {
// We have a complete command // We have a complete command
return GetCompleteNTTransactResponse(header, request.Function, request.Setup, request.TransParameters, request.TransData, share, state, sendQueue); return GetCompleteNTTransactResponse(header, request.Function, request.Setup, request.TransParameters, request.TransData, share, state);
} }
} }
@ -45,7 +45,7 @@ namespace SMBLibrary.Server.SMB1
/// There are no secondary response messages. /// There are no secondary response messages.
/// The client MUST send as many secondary requests as are needed to complete the transfer of the transaction request. /// The client MUST send as many secondary requests as are needed to complete the transfer of the transaction request.
/// </summary> /// </summary>
internal static SMB1Command GetNTTransactResponse(SMB1Header header, NTTransactSecondaryRequest request, ISMBShare share, SMB1ConnectionState state, List<SMB1Command> sendQueue) internal static List<SMB1Command> GetNTTransactResponse(SMB1Header header, NTTransactSecondaryRequest request, ISMBShare share, SMB1ConnectionState state)
{ {
ProcessStateObject processState = state.GetProcessState(header.PID); ProcessStateObject processState = state.GetProcessState(header.PID);
if (processState == null) if (processState == null)
@ -60,16 +60,16 @@ namespace SMBLibrary.Server.SMB1
if (processState.TransactionParametersReceived < processState.TransactionParameters.Length || if (processState.TransactionParametersReceived < processState.TransactionParameters.Length ||
processState.TransactionDataReceived < processState.TransactionData.Length) processState.TransactionDataReceived < processState.TransactionData.Length)
{ {
return null; return new List<SMB1Command>();
} }
else else
{ {
// We have a complete command // We have a complete command
return GetCompleteNTTransactResponse(header, (NTTransactSubcommandName)processState.SubcommandID, processState.TransactionSetup, processState.TransactionParameters, processState.TransactionData, share, state, sendQueue); return GetCompleteNTTransactResponse(header, (NTTransactSubcommandName)processState.SubcommandID, processState.TransactionSetup, processState.TransactionParameters, processState.TransactionData, share, state);
} }
} }
internal static SMB1Command GetCompleteNTTransactResponse(SMB1Header header, NTTransactSubcommandName subcommandName, byte[] requestSetup, byte[] requestParameters, byte[] requestData, ISMBShare share, SMB1ConnectionState state, List<SMB1Command> sendQueue) internal static List<SMB1Command> GetCompleteNTTransactResponse(SMB1Header header, NTTransactSubcommandName subcommandName, byte[] requestSetup, byte[] requestParameters, byte[] requestData, ISMBShare share, SMB1ConnectionState state)
{ {
NTTransactSubcommand subcommand = NTTransactSubcommand.GetSubcommandRequest(subcommandName, requestSetup, requestParameters, requestData, header.UnicodeFlag); NTTransactSubcommand subcommand = NTTransactSubcommand.GetSubcommandRequest(subcommandName, requestSetup, requestParameters, requestData, header.UnicodeFlag);
NTTransactSubcommand subcommandResponse = null; NTTransactSubcommand subcommandResponse = null;
@ -107,9 +107,7 @@ namespace SMBLibrary.Server.SMB1
byte[] responseSetup = subcommandResponse.GetSetup(); byte[] responseSetup = subcommandResponse.GetSetup();
byte[] responseParameters = subcommandResponse.GetParameters(header.UnicodeFlag); byte[] responseParameters = subcommandResponse.GetParameters(header.UnicodeFlag);
byte[] responseData = subcommandResponse.GetData(); byte[] responseData = subcommandResponse.GetData();
NTTransactResponse response = new NTTransactResponse(); return GetNTTransactResponse(responseSetup, responseParameters, responseData, state.MaxBufferSize);
PrepareResponse(response, responseSetup, responseParameters, responseData, state.MaxBufferSize, sendQueue);
return response;
} }
private static NTTransactIOCTLResponse GetSubcommandResponse(SMB1Header header, NTTransactIOCTLRequest subcommand, ISMBShare share, SMB1ConnectionState state) private static NTTransactIOCTLResponse GetSubcommandResponse(SMB1Header header, NTTransactIOCTLRequest subcommand, ISMBShare share, SMB1ConnectionState state)
@ -143,15 +141,17 @@ namespace SMBLibrary.Server.SMB1
} }
} }
private static void PrepareResponse(NTTransactResponse response, byte[] responseSetup, byte[] responseParameters, byte[] responseData, int maxBufferSize, List<SMB1Command> sendQueue) private static List<SMB1Command> GetNTTransactResponse(byte[] responseSetup, byte[] responseParameters, byte[] responseData, int maxBufferSize)
{ {
if (NTTransactResponse.CalculateMessageSize(responseSetup.Length, responseParameters.Length, responseData.Length) <= maxBufferSize) if (NTTransactResponse.CalculateMessageSize(responseSetup.Length, responseParameters.Length, responseData.Length) <= maxBufferSize)
{ {
NTTransactResponse response = new NTTransactResponse();
response.Setup = responseSetup; response.Setup = responseSetup;
response.TotalParameterCount = (ushort)responseParameters.Length; response.TotalParameterCount = (ushort)responseParameters.Length;
response.TotalDataCount = (ushort)responseData.Length; response.TotalDataCount = (ushort)responseData.Length;
response.TransParameters = responseParameters; response.TransParameters = responseParameters;
response.TransData = responseData; response.TransData = responseData;
return response;
} }
else else
{ {

View file

@ -43,17 +43,15 @@ namespace SMBLibrary.Server.SMB1
return new FindClose2Response(); return new FindClose2Response();
} }
internal static EchoResponse GetEchoResponse(EchoRequest request, List<SMB1Command> sendQueue) internal static List<SMB1Command> GetEchoResponse(EchoRequest request)
{ {
EchoResponse response = new EchoResponse(); List<SMB1Command> response = new List<SMB1Command>();
response.SequenceNumber = 0; for (int index = 0; index < request.EchoCount; index++)
response.SMBData = request.SMBData;
for (int index = 1; index < request.EchoCount; index++)
{ {
EchoResponse echo = new EchoResponse(); EchoResponse echo = new EchoResponse();
echo.SequenceNumber = (ushort)index; echo.SequenceNumber = (ushort)index;
echo.SMBData = request.SMBData; echo.SMBData = request.SMBData;
sendQueue.Add(echo); response.Add(echo);
} }
return response; return response;
} }

View file

@ -21,7 +21,7 @@ namespace SMBLibrary.Server.SMB1
/// The client MUST send as many secondary requests as are needed to complete the transfer of the transaction request. /// The client MUST send as many secondary requests as are needed to complete the transfer of the transaction request.
/// The server MUST respond to the transaction request as a whole. /// The server MUST respond to the transaction request as a whole.
/// </summary> /// </summary>
internal static SMB1Command GetTransactionResponse(SMB1Header header, TransactionRequest request, ISMBShare share, SMB1ConnectionState state, List<SMB1Command> sendQueue) internal static List<SMB1Command> GetTransactionResponse(SMB1Header header, TransactionRequest request, ISMBShare share, SMB1ConnectionState state)
{ {
ProcessStateObject processState = state.ObtainProcessState(header.PID); ProcessStateObject processState = state.ObtainProcessState(header.PID);
processState.MaxDataCount = request.MaxDataCount; processState.MaxDataCount = request.MaxDataCount;
@ -38,18 +38,18 @@ namespace SMBLibrary.Server.SMB1
ByteWriter.WriteBytes(processState.TransactionData, 0, request.TransData); ByteWriter.WriteBytes(processState.TransactionData, 0, request.TransData);
processState.TransactionParametersReceived += request.TransParameters.Length; processState.TransactionParametersReceived += request.TransParameters.Length;
processState.TransactionDataReceived += request.TransData.Length; processState.TransactionDataReceived += request.TransData.Length;
return null; return new List<SMB1Command>();
} }
else else
{ {
// We have a complete command // We have a complete command
if (request is Transaction2Request) if (request is Transaction2Request)
{ {
return GetCompleteTransaction2Response(header, request.Setup, request.TransParameters, request.TransData, share, state, sendQueue); return GetCompleteTransaction2Response(header, request.Setup, request.TransParameters, request.TransData, share, state);
} }
else else
{ {
return GetCompleteTransactionResponse(header, request.Name, request.Setup, request.TransParameters, request.TransData, share, state, sendQueue); return GetCompleteTransactionResponse(header, request.Name, request.Setup, request.TransParameters, request.TransData, share, state);
} }
} }
} }
@ -59,7 +59,7 @@ namespace SMBLibrary.Server.SMB1
/// The client MUST send as many secondary requests as are needed to complete the transfer of the transaction request. /// The client MUST send as many secondary requests as are needed to complete the transfer of the transaction request.
/// The server MUST respond to the transaction request as a whole. /// The server MUST respond to the transaction request as a whole.
/// </summary> /// </summary>
internal static SMB1Command GetTransactionResponse(SMB1Header header, TransactionSecondaryRequest request, ISMBShare share, SMB1ConnectionState state, List<SMB1Command> sendQueue) internal static List<SMB1Command> GetTransactionResponse(SMB1Header header, TransactionSecondaryRequest request, ISMBShare share, SMB1ConnectionState state)
{ {
ProcessStateObject processState = state.GetProcessState(header.PID); ProcessStateObject processState = state.GetProcessState(header.PID);
if (processState == null) if (processState == null)
@ -74,23 +74,23 @@ namespace SMBLibrary.Server.SMB1
if (processState.TransactionParametersReceived < processState.TransactionParameters.Length || if (processState.TransactionParametersReceived < processState.TransactionParameters.Length ||
processState.TransactionDataReceived < processState.TransactionData.Length) processState.TransactionDataReceived < processState.TransactionData.Length)
{ {
return null; return new List<SMB1Command>();
} }
else else
{ {
// We have a complete command // We have a complete command
if (request is Transaction2SecondaryRequest) if (request is Transaction2SecondaryRequest)
{ {
return GetCompleteTransaction2Response(header, processState.TransactionSetup, processState.TransactionParameters, processState.TransactionData, share, state, sendQueue); return GetCompleteTransaction2Response(header, processState.TransactionSetup, processState.TransactionParameters, processState.TransactionData, share, state);
} }
else else
{ {
return GetCompleteTransactionResponse(header, processState.Name, processState.TransactionSetup, processState.TransactionParameters, processState.TransactionData, share, state, sendQueue); return GetCompleteTransactionResponse(header, processState.Name, processState.TransactionSetup, processState.TransactionParameters, processState.TransactionData, share, state);
} }
} }
} }
internal static SMB1Command GetCompleteTransactionResponse(SMB1Header header, string name, byte[] requestSetup, byte[] requestParameters, byte[] requestData, ISMBShare share, SMB1ConnectionState state, List<SMB1Command> sendQueue) internal static List<SMB1Command> GetCompleteTransactionResponse(SMB1Header header, string name, byte[] requestSetup, byte[] requestParameters, byte[] requestData, ISMBShare share, SMB1ConnectionState state)
{ {
if (String.Equals(name, @"\pipe\lanman", StringComparison.InvariantCultureIgnoreCase)) if (String.Equals(name, @"\pipe\lanman", StringComparison.InvariantCultureIgnoreCase))
{ {
@ -169,12 +169,10 @@ namespace SMBLibrary.Server.SMB1
byte[] responseSetup = subcommandResponse.GetSetup(); byte[] responseSetup = subcommandResponse.GetSetup();
byte[] responseParameters = subcommandResponse.GetParameters(header.UnicodeFlag); byte[] responseParameters = subcommandResponse.GetParameters(header.UnicodeFlag);
byte[] responseData = subcommandResponse.GetData(); byte[] responseData = subcommandResponse.GetData();
TransactionResponse response = new TransactionResponse(); return GetTransactionResponse(false, responseSetup, responseParameters, responseData, state.MaxBufferSize);
PrepareResponse(response, responseSetup, responseParameters, responseData, state.MaxBufferSize, sendQueue);
return response;
} }
internal static SMB1Command GetCompleteTransaction2Response(SMB1Header header, byte[] requestSetup, byte[] requestParameters, byte[] requestData, ISMBShare share, SMB1ConnectionState state, List<SMB1Command> sendQueue) internal static List<SMB1Command> GetCompleteTransaction2Response(SMB1Header header, byte[] requestSetup, byte[] requestParameters, byte[] requestData, ISMBShare share, SMB1ConnectionState state)
{ {
Transaction2Subcommand subcommand; Transaction2Subcommand subcommand;
try try
@ -237,13 +235,22 @@ namespace SMBLibrary.Server.SMB1
byte[] responseSetup = subcommandResponse.GetSetup(); byte[] responseSetup = subcommandResponse.GetSetup();
byte[] responseParameters = subcommandResponse.GetParameters(header.UnicodeFlag); byte[] responseParameters = subcommandResponse.GetParameters(header.UnicodeFlag);
byte[] responseData = subcommandResponse.GetData(header.UnicodeFlag); byte[] responseData = subcommandResponse.GetData(header.UnicodeFlag);
Transaction2Response response = new Transaction2Response(); return GetTransactionResponse(true, responseSetup, responseParameters, responseData, state.MaxBufferSize);
PrepareResponse(response, responseSetup, responseParameters, responseData, state.MaxBufferSize, sendQueue);
return response;
} }
internal static void PrepareResponse(TransactionResponse response, byte[] responseSetup, byte[] responseParameters, byte[] responseData, int maxBufferSize, List<SMB1Command> sendQueue) internal static List<SMB1Command> GetTransactionResponse(bool transaction2Response, byte[] responseSetup, byte[] responseParameters, byte[] responseData, int maxBufferSize)
{ {
List<SMB1Command> result = new List<SMB1Command>();
TransactionResponse response;
if (transaction2Response)
{
response = new Transaction2Response();
}
else
{
response = new TransactionResponse();
}
result.Add(response);
int responseSize = TransactionResponse.CalculateMessageSize(responseSetup.Length, responseParameters.Length, responseData.Length); int responseSize = TransactionResponse.CalculateMessageSize(responseSetup.Length, responseParameters.Length, responseData.Length);
if (responseSize <= maxBufferSize) if (responseSize <= maxBufferSize)
{ {
@ -268,7 +275,7 @@ namespace SMBLibrary.Server.SMB1
while (dataBytesLeftToSend > 0) while (dataBytesLeftToSend > 0)
{ {
TransactionResponse additionalResponse; TransactionResponse additionalResponse;
if (response is Transaction2Response) if (transaction2Response)
{ {
additionalResponse = new Transaction2Response(); additionalResponse = new Transaction2Response();
} }
@ -290,11 +297,12 @@ namespace SMBLibrary.Server.SMB1
additionalResponse.TransData = buffer; additionalResponse.TransData = buffer;
additionalResponse.ParameterDisplacement = (ushort)response.TransParameters.Length; additionalResponse.ParameterDisplacement = (ushort)response.TransParameters.Length;
additionalResponse.DataDisplacement = (ushort)dataBytesSent; additionalResponse.DataDisplacement = (ushort)dataBytesSent;
sendQueue.Add(additionalResponse); result.Add(additionalResponse);
dataBytesLeftToSend -= currentDataLength; dataBytesLeftToSend -= currentDataLength;
} }
} }
return result;
} }
} }
} }

View file

@ -17,41 +17,55 @@ namespace SMBLibrary.Server
{ {
public void ProcessSMB1Message(SMB1Message message, ref ConnectionState state) public void ProcessSMB1Message(SMB1Message message, ref ConnectionState state)
{ {
SMB1Message reply = new SMB1Message(); SMB1Header header = new SMB1Header();
PrepareResponseHeader(reply, message); PrepareResponseHeader(header, message.Header);
List<SMB1Command> sendQueue = new List<SMB1Command>(); List<SMB1Command> sendQueue = new List<SMB1Command>();
bool isBatchedRequest = (message.Commands.Count > 1);
foreach (SMB1Command command in message.Commands) foreach (SMB1Command command in message.Commands)
{ {
SMB1Command response = ProcessSMB1Command(reply.Header, command, ref state, sendQueue); List<SMB1Command> responses = ProcessSMB1Command(header, command, ref state);
if (response != null) sendQueue.AddRange(responses);
{
reply.Commands.Add(response); if (header.Status != NTStatus.STATUS_SUCCESS)
}
if (reply.Header.Status != NTStatus.STATUS_SUCCESS)
{ {
break; break;
} }
} }
if (reply.Commands.Count > 0) if (isBatchedRequest)
{ {
TrySendMessage(state, reply); if (sendQueue.Count > 0)
foreach (SMB1Command command in sendQueue)
{ {
SMB1Message secondaryReply = new SMB1Message(); // The server MUST batch the response into an AndX Response chain.
secondaryReply.Header = reply.Header; SMB1Message reply = new SMB1Message();
secondaryReply.Commands.Add(command); reply.Header = header;
TrySendMessage(state, secondaryReply); for (int index = 0; index < sendQueue.Count; index++)
{
if (sendQueue[index] is SMBAndXCommand || index == sendQueue.Count - 1)
{
reply.Commands.Add(sendQueue[index]);
sendQueue.RemoveAt(index);
index--;
} }
} }
TrySendMessage(state, reply);
}
}
foreach (SMB1Command response in sendQueue)
{
SMB1Message reply = new SMB1Message();
reply.Header = header;
reply.Commands.Add(response);
TrySendMessage(state, reply);
}
} }
/// <summary> /// <summary>
/// May return null /// May return an empty list
/// </summary> /// </summary>
public SMB1Command ProcessSMB1Command(SMB1Header header, SMB1Command command, ref ConnectionState state, List<SMB1Command> sendQueue) public List<SMB1Command> ProcessSMB1Command(SMB1Header header, SMB1Command command, ref ConnectionState state)
{ {
if (state.ServerDialect == SMBDialect.NotSet) if (state.ServerDialect == SMBDialect.NotSet)
{ {
@ -92,11 +106,11 @@ namespace SMBLibrary.Server
} }
else else
{ {
return ProcessSMB1Command(header, command, (SMB1ConnectionState)state, sendQueue); return ProcessSMB1Command(header, command, (SMB1ConnectionState)state);
} }
} }
private SMB1Command ProcessSMB1Command(SMB1Header header, SMB1Command command, SMB1ConnectionState state, List<SMB1Command> sendQueue) private List<SMB1Command> ProcessSMB1Command(SMB1Header header, SMB1Command command, SMB1ConnectionState state)
{ {
if (command is SessionSetupAndXRequest) if (command is SessionSetupAndXRequest)
{ {
@ -112,7 +126,7 @@ namespace SMBLibrary.Server
} }
else if (command is EchoRequest) else if (command is EchoRequest)
{ {
return ServerResponseHelper.GetEchoResponse((EchoRequest)command, sendQueue); return ServerResponseHelper.GetEchoResponse((EchoRequest)command);
} }
else else
{ {
@ -244,7 +258,7 @@ namespace SMBLibrary.Server
TransactionRequest request = (TransactionRequest)command; TransactionRequest request = (TransactionRequest)command;
try try
{ {
return TransactionHelper.GetTransactionResponse(header, request, share, state, sendQueue); return TransactionHelper.GetTransactionResponse(header, request, share, state);
} }
catch (UnsupportedInformationLevelException) catch (UnsupportedInformationLevelException)
{ {
@ -257,7 +271,7 @@ namespace SMBLibrary.Server
TransactionSecondaryRequest request = (TransactionSecondaryRequest)command; TransactionSecondaryRequest request = (TransactionSecondaryRequest)command;
try try
{ {
return TransactionHelper.GetTransactionResponse(header, request, share, state, sendQueue); return TransactionHelper.GetTransactionResponse(header, request, share, state);
} }
catch (UnsupportedInformationLevelException) catch (UnsupportedInformationLevelException)
{ {
@ -268,12 +282,12 @@ namespace SMBLibrary.Server
else if (command is NTTransactRequest) else if (command is NTTransactRequest)
{ {
NTTransactRequest request = (NTTransactRequest)command; NTTransactRequest request = (NTTransactRequest)command;
return NTTransactHelper.GetNTTransactResponse(header, request, share, state, sendQueue); return NTTransactHelper.GetNTTransactResponse(header, request, share, state);
} }
else if (command is NTTransactSecondaryRequest) else if (command is NTTransactSecondaryRequest)
{ {
NTTransactSecondaryRequest request = (NTTransactSecondaryRequest)command; NTTransactSecondaryRequest request = (NTTransactSecondaryRequest)command;
return NTTransactHelper.GetNTTransactResponse(header, request, share, state, sendQueue); return NTTransactHelper.GetNTTransactResponse(header, request, share, state);
} }
else if (command is NTCreateAndXRequest) else if (command is NTCreateAndXRequest)
{ {
@ -295,31 +309,31 @@ namespace SMBLibrary.Server
state.LogToServer(Severity.Verbose, "SMB1 message sent: {0} responses, First response: {1}, Packet length: {2}", response.Commands.Count, response.Commands[0].CommandName.ToString(), packet.Length); state.LogToServer(Severity.Verbose, "SMB1 message sent: {0} responses, First response: {1}, Packet length: {2}", response.Commands.Count, response.Commands[0].CommandName.ToString(), packet.Length);
} }
private static void PrepareResponseHeader(SMB1Message response, SMB1Message request) private static void PrepareResponseHeader(SMB1Header responseHeader, SMB1Header requestHeader)
{ {
response.Header.Status = NTStatus.STATUS_SUCCESS; responseHeader.Status = NTStatus.STATUS_SUCCESS;
response.Header.Flags = HeaderFlags.CaseInsensitive | HeaderFlags.CanonicalizedPaths | HeaderFlags.Reply; responseHeader.Flags = HeaderFlags.CaseInsensitive | HeaderFlags.CanonicalizedPaths | HeaderFlags.Reply;
response.Header.Flags2 = HeaderFlags2.NTStatusCode; responseHeader.Flags2 = HeaderFlags2.NTStatusCode;
if ((request.Header.Flags2 & HeaderFlags2.LongNamesAllowed) > 0) if ((requestHeader.Flags2 & HeaderFlags2.LongNamesAllowed) > 0)
{ {
response.Header.Flags2 |= HeaderFlags2.LongNamesAllowed | HeaderFlags2.LongNameUsed; responseHeader.Flags2 |= HeaderFlags2.LongNamesAllowed | HeaderFlags2.LongNameUsed;
} }
if ((request.Header.Flags2 & HeaderFlags2.ExtendedAttributes) > 0) if ((requestHeader.Flags2 & HeaderFlags2.ExtendedAttributes) > 0)
{ {
response.Header.Flags2 |= HeaderFlags2.ExtendedAttributes; responseHeader.Flags2 |= HeaderFlags2.ExtendedAttributes;
} }
if ((request.Header.Flags2 & HeaderFlags2.ExtendedSecurity) > 0) if ((requestHeader.Flags2 & HeaderFlags2.ExtendedSecurity) > 0)
{ {
response.Header.Flags2 |= HeaderFlags2.ExtendedSecurity; responseHeader.Flags2 |= HeaderFlags2.ExtendedSecurity;
} }
if ((request.Header.Flags2 & HeaderFlags2.Unicode) > 0) if ((requestHeader.Flags2 & HeaderFlags2.Unicode) > 0)
{ {
response.Header.Flags2 |= HeaderFlags2.Unicode; responseHeader.Flags2 |= HeaderFlags2.Unicode;
} }
response.Header.MID = request.Header.MID; responseHeader.MID = requestHeader.MID;
response.Header.PID = request.Header.PID; responseHeader.PID = requestHeader.PID;
response.Header.UID = request.Header.UID; responseHeader.UID = requestHeader.UID;
response.Header.TID = request.Header.TID; responseHeader.TID = requestHeader.TID;
} }
} }
} }