Skip to content

Commit

Permalink
U/sgriffin/mapi (#79)
Browse files Browse the repository at this point in the history
* Hex arrays should actually be in hex

* suppress cb on PtypBinary since we already have Count field

* Annotate a few more MAPI data types

* quote strings

* anotate integer16

* unknown proptag should still be hex

* add generic array parsing

* Simplify array output

* Don't crash copying nothing

* Parse StateProperty and add some prop tags
  • Loading branch information
stephenegriffin committed Oct 26, 2023
1 parent 54bc2aa commit 8a4a3c1
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 41 deletions.
5 changes: 4 additions & 1 deletion MAPIInspector/Source/MAPIControl.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 9 additions & 26 deletions MAPIInspector/Source/Parsers/BaseStructure.cs
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ public static TreeNode AddNodesForTree(string nodeName, object obj, int startInd
// the size of underlying type of enum.
Type fieldType = type;

TreeNode tn = new TreeNode(string.Format("{0}:{1}", info[i].Name, EnumToString(info[i].GetValue(obj))));
TreeNode tn = new TreeNode(string.Format("{0}:{1}", info[i].Name, Utilities.EnumToString(info[i].GetValue(obj))));
res.Nodes.Add(tn);

if (type.Name == "String")
Expand Down Expand Up @@ -418,19 +418,19 @@ public static TreeNode AddNodesForTree(string nodeName, object obj, int startInd
result.Append(tempbye.ToString("X2"));
}
}
else if (arr.GetType().ToString() == "System.Byte[]")
else if (arr.Length > 0)
{
result.Append(Utilities.ConvertArrayToHexString((byte[])arr));
}
else if (arr.GetType().ToString() == "System.Uint[]")
{
result.Append(Utilities.ConvertArrayToHexString((uint[])arr));
result.Append(Utilities.ConvertArrayToHexString(arr));
}

TreeNode tn = new TreeNode($"{info[i].Name}:{result.ToString()}");
res.Nodes.Add(tn);
// Add subnode with length of array
tn.Nodes.Add(new TreeNode($"cb:{arr.Length}"));

if (!(obj is PtypBinary))
{
// Add subnode with length of array
tn.Nodes.Add(new TreeNode($"cb:{arr.Length}"));
}

for (int j = 0; j < arr.Length; j++)
{
Expand Down Expand Up @@ -1007,23 +1007,6 @@ protected long RemainingBytes()
return this.stream.Length - this.stream.Position;
}

/// <summary>
/// Converts a simple (non-flag) enum to string. If the value is not present in the underlying enum, converts to a hex string.
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
private static string EnumToString(object obj)
{
if (Enum.IsDefined(obj.GetType(), obj))
{
return obj.ToString();
}
else
{
return $"0x{Convert.ToUInt64(obj):X}";
}
}

/// <summary>
/// Record start position and byte counts consumed
/// </summary>
Expand Down
32 changes: 24 additions & 8 deletions MAPIInspector/Source/Parsers/MSOXCDATA.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4822,14 +4822,15 @@ public override void Parse(Stream s)
{
PropertyValue propValue = new PropertyValue(tempPropTag.PropertyType);
propValue.Parse(s);
propValue.PropertyTag = $"{tempPropTag.PropertyType}:{tempPropTag.PropertyId}";
//todo
propValue.PropertyTag = $"{tempPropTag.PropertyType}:{Utilities.EnumToString(tempPropTag.PropertyId)}";
rowPropValue = propValue;
}
else
{
TypedPropertyValue typePropValue = new TypedPropertyValue();
typePropValue.Parse(s);
typePropValue.PropertyTag = $"{tempPropTag.PropertyType}:{tempPropTag.PropertyId}";
typePropValue.PropertyTag = $"{tempPropTag.PropertyType}:{Utilities.EnumToString(tempPropTag.PropertyId)}";
rowPropValue = typePropValue;
}
}
Expand All @@ -4839,14 +4840,14 @@ public override void Parse(Stream s)
{
FlaggedPropertyValue flagPropValue = new FlaggedPropertyValue(tempPropTag.PropertyType);
flagPropValue.Parse(s);
flagPropValue.PropertyTag = $"{tempPropTag.PropertyType}:{tempPropTag.PropertyId}";
flagPropValue.PropertyTag = $"{tempPropTag.PropertyType}:{Utilities.EnumToString(tempPropTag.PropertyId)}";
rowPropValue = flagPropValue;
}
else
{
FlaggedPropertyValueWithType flagPropValue = new FlaggedPropertyValueWithType();
flagPropValue.Parse(s);
flagPropValue.PropertyTag = $"{tempPropTag.PropertyType}:{tempPropTag.PropertyId}";
flagPropValue.PropertyTag = $"{tempPropTag.PropertyType}:{Utilities.EnumToString(tempPropTag.PropertyId)}";
rowPropValue = flagPropValue;
}
}
Expand Down Expand Up @@ -5192,7 +5193,7 @@ public override void Parse(Stream s)
/// <summary>
/// 2 bytes; a 16-bit integer. [MS-DTYP]: INT16
/// </summary>
public class PtypInteger16 : BaseStructure
public class PtypInteger16 : AnnotatedData
{
/// <summary>
/// 16-bit integer.
Expand All @@ -5207,13 +5208,16 @@ public override void Parse(Stream s)
{
base.Parse(s);
this.Value = this.ReadINT16();
this.ParsedValue = $"{Value}";
}

public override int Size { get; } = 2;
}

/// <summary>
/// 4 bytes; a 32-bit integer. [MS-DTYP]: INT32
/// </summary>
public class PtypInteger32 : BaseStructure
public class PtypInteger32 : AnnotatedData
{
/// <summary>
/// 32-bit integer.
Expand All @@ -5228,7 +5232,10 @@ public override void Parse(Stream s)
{
base.Parse(s);
this.Value = this.ReadINT32();
this.ParsedValue = $"{Value}";
}

public override int Size { get; } = 4;
}

/// <summary>
Expand Down Expand Up @@ -5339,7 +5346,7 @@ public override void Parse(Stream s)
/// <summary>
/// 1 byte; restricted to 1 or 0.
/// </summary>
public class PtypBoolean : BaseStructure
public class PtypBoolean : AnnotatedData
{
/// <summary>
/// 1 byte; restricted to 1 or 0.
Expand All @@ -5354,7 +5361,10 @@ public override void Parse(Stream s)
{
base.Parse(s);
this.Value = this.ReadBoolean();
this.ParsedValue = Value.ToString();
}

public override int Size { get; } = 1;
}

/// <summary>
Expand All @@ -5381,7 +5391,7 @@ public override void Parse(Stream s)
/// <summary>
/// Variable size; a string of Unicode characters in UTF-16LE format encoding with terminating null character (0x0000).
/// </summary>
public class PtypString : BaseStructure
public class PtypString : AnnotatedData
{
/// <summary>
/// A string of Unicode characters in UTF-16LE format encoding with terminating null character (0x0000).
Expand Down Expand Up @@ -5411,6 +5421,12 @@ public override void Parse(Stream s)
base.Parse(s);
this.Value = new MAPIString(Encoding.Unicode, "\0", this.length);
this.Value.Parse(s);
this.ParsedValue = $"\"{Value}\"";
}

public override int Size
{
get { return Value.Size; }
}
}

Expand Down
6 changes: 4 additions & 2 deletions MAPIInspector/Source/Parsers/MSOXCFXICS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2576,7 +2576,7 @@ public class RopSynchronizationUploadStateStreamBeginRequest : BaseStructure
/// <summary>
/// A PropertyTag structure.
/// </summary>
public uint StateProperty;
public PropertyTag StateProperty;

/// <summary>
/// An unsigned integer that specifies the size of the stream to be uploaded.
Expand All @@ -2594,7 +2594,9 @@ public override void Parse(Stream s)
this.RopId = (RopIdType)this.ReadByte();
this.LogonId = this.ReadByte();
this.InputHandleIndex = this.ReadByte();
this.StateProperty = this.ReadUint();
this.StateProperty = new PropertyTag();
this.StateProperty.Parse(s);

this.TransferBufferSize = this.ReadUint();
}
}
Expand Down
47 changes: 46 additions & 1 deletion MAPIInspector/Source/Parsers/MSOXPROPS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2867,7 +2867,52 @@ public enum PidTagPropertyEnum : ushort
/// <summary>
/// The MetaTagDnPrefix meta-property MUST be ignored when received
/// </summary>
MetaTagDnPrefix = 0x4008
MetaTagDnPrefix = 0x4008,

/// <summary>
/// Contains a count of the significant characters of the message text.
/// </summary>
PidTagRtfSyncBodyCount = 0x1007,

/// <summary>
/// Contains significant characters that appear at the beginning of the message text.
/// </summary>
PidTagRtfSyncBodyTag = 0x1008,

/// <summary>
/// Contains a count of the ignorable characters that appear before the significant characters of the message.
/// </summary>
PidTagRtfSyncPrefixCount = 0x1010,

/// <summary>
/// Contains a count of the ignorable characters that appear after the significant characters of the message.
/// </summary>
PidTagRtfSyncTrailingCount = 0x1011,

/// <summary>
/// The OrigEntryId
/// </summary>
OrigEntryId = 0x300F,

/// <summary>
/// he MetaTagIdsetGiven property contains a serialization of REPLGUID-based IDSET structures, as specified in section 2.2.2.4.2.
/// </summary>
MetaTagIdsetGiven = 0x4017,

/// <summary>
/// The MetaTagCnsetSeen property contains a serialization of REPLGUID-based CNSET structures, as specified in section 2.2.2.4.
/// </summary>
MetaTagCnsetSeen = 0x6796,

/// <summary>
/// The MetaTagCnsetRead property contains a serialization of REPLGUID-based CNSET structures, as specified in section 2.2.2.4.
/// </summary>
MetaTagCnsetRead = 0x67D2,

/// <summary>
/// The MetaTagCnsetSeenFAI property contains a serialization of REPLGUID-based IDSET structures, as specified in section 2.2.2.4.
/// </summary>
MetaTagCnsetSeenFAI = 0x67DA
}

/// <summary>
Expand Down
23 changes: 20 additions & 3 deletions MAPIInspector/Source/Utilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,15 @@ public static string ConvertByteArrayToString(byte[] bin, uint? limit = null)
}

// Array type just display the first 30 values if the array length is more than 30.
public static string ConvertArrayToHexString<T>(T[] bin, int? limit = 30)
public static string ConvertArrayToHexString(Array bin, int? limit = 30)
{
var result = new StringBuilder();
int displayLength = limit.HasValue ? limit.Value : bin.Length;
int displayLength = limit ?? bin.Length;
result.Append("[");

foreach (var b in bin)
{
result.Append(b.ToString() + ",");
result.Append($"{b:X2},");

if (displayLength <= 1)
{
Expand Down Expand Up @@ -213,5 +213,22 @@ public static string ConvertCSharpToJson(int id, bool isRequest, object obj)
SealTheObject sealTheObject = new SealTheObject(id, isRequest, obj);
return JsonConvert.SerializeObject((object)sealTheObject);
}

/// <summary>
/// Converts a simple (non-flag) enum to string. If the value is not present in the underlying enum, converts to a hex string.
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static string EnumToString(object obj)
{
if (Enum.IsDefined(obj.GetType(), obj))
{
return obj.ToString();
}
else
{
return $"0x{Convert.ToUInt64(obj):X}";
}
}
}
}

0 comments on commit 8a4a3c1

Please sign in to comment.