diff --git a/MAPIInspector/Source/MAPIControl.Designer.cs b/MAPIInspector/Source/MAPIControl.Designer.cs index 2ae3ec7..b85f387 100644 --- a/MAPIInspector/Source/MAPIControl.Designer.cs +++ b/MAPIInspector/Source/MAPIControl.Designer.cs @@ -181,7 +181,10 @@ void CopyMethod(object sender, EventArgs e, Be.Windows.Forms.HexBox hexBox) byte[] targetBytes = new byte[hexBox.SelectionLength]; Array.Copy(hexBox.GetAllBytes(), hexBox.SelectionStart, targetBytes, 0, hexBox.SelectionLength); string hex = BitConverter.ToString(targetBytes).Replace("-", string.Empty); - Clipboard.SetText(hex); + if (!string.IsNullOrEmpty(hex)) + { + Clipboard.SetText(hex); + } } void MAPI_Copy(object sender, EventArgs e) diff --git a/MAPIInspector/Source/Parsers/BaseStructure.cs b/MAPIInspector/Source/Parsers/BaseStructure.cs index 00eb594..3ec0b58 100644 --- a/MAPIInspector/Source/Parsers/BaseStructure.cs +++ b/MAPIInspector/Source/Parsers/BaseStructure.cs @@ -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") @@ -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++) { @@ -1007,23 +1007,6 @@ protected long RemainingBytes() return this.stream.Length - this.stream.Position; } - /// - /// Converts a simple (non-flag) enum to string. If the value is not present in the underlying enum, converts to a hex string. - /// - /// - /// - private static string EnumToString(object obj) - { - if (Enum.IsDefined(obj.GetType(), obj)) - { - return obj.ToString(); - } - else - { - return $"0x{Convert.ToUInt64(obj):X}"; - } - } - /// /// Record start position and byte counts consumed /// diff --git a/MAPIInspector/Source/Parsers/MSOXCDATA.cs b/MAPIInspector/Source/Parsers/MSOXCDATA.cs index 7e937f0..4b4d4dd 100644 --- a/MAPIInspector/Source/Parsers/MSOXCDATA.cs +++ b/MAPIInspector/Source/Parsers/MSOXCDATA.cs @@ -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; } } @@ -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; } } @@ -5192,7 +5193,7 @@ public override void Parse(Stream s) /// /// 2 bytes; a 16-bit integer. [MS-DTYP]: INT16 /// - public class PtypInteger16 : BaseStructure + public class PtypInteger16 : AnnotatedData { /// /// 16-bit integer. @@ -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; } /// /// 4 bytes; a 32-bit integer. [MS-DTYP]: INT32 /// - public class PtypInteger32 : BaseStructure + public class PtypInteger32 : AnnotatedData { /// /// 32-bit integer. @@ -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; } /// @@ -5339,7 +5346,7 @@ public override void Parse(Stream s) /// /// 1 byte; restricted to 1 or 0. /// - public class PtypBoolean : BaseStructure + public class PtypBoolean : AnnotatedData { /// /// 1 byte; restricted to 1 or 0. @@ -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; } /// @@ -5381,7 +5391,7 @@ public override void Parse(Stream s) /// /// Variable size; a string of Unicode characters in UTF-16LE format encoding with terminating null character (0x0000). /// - public class PtypString : BaseStructure + public class PtypString : AnnotatedData { /// /// A string of Unicode characters in UTF-16LE format encoding with terminating null character (0x0000). @@ -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; } } } diff --git a/MAPIInspector/Source/Parsers/MSOXCFXICS.cs b/MAPIInspector/Source/Parsers/MSOXCFXICS.cs index 35bf1b4..e23d268 100644 --- a/MAPIInspector/Source/Parsers/MSOXCFXICS.cs +++ b/MAPIInspector/Source/Parsers/MSOXCFXICS.cs @@ -2576,7 +2576,7 @@ public class RopSynchronizationUploadStateStreamBeginRequest : BaseStructure /// /// A PropertyTag structure. /// - public uint StateProperty; + public PropertyTag StateProperty; /// /// An unsigned integer that specifies the size of the stream to be uploaded. @@ -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(); } } diff --git a/MAPIInspector/Source/Parsers/MSOXPROPS.cs b/MAPIInspector/Source/Parsers/MSOXPROPS.cs index f457b28..bfd5bbe 100644 --- a/MAPIInspector/Source/Parsers/MSOXPROPS.cs +++ b/MAPIInspector/Source/Parsers/MSOXPROPS.cs @@ -2867,7 +2867,52 @@ public enum PidTagPropertyEnum : ushort /// /// The MetaTagDnPrefix meta-property MUST be ignored when received /// - MetaTagDnPrefix = 0x4008 + MetaTagDnPrefix = 0x4008, + + /// + /// Contains a count of the significant characters of the message text. + /// + PidTagRtfSyncBodyCount = 0x1007, + + /// + /// Contains significant characters that appear at the beginning of the message text. + /// + PidTagRtfSyncBodyTag = 0x1008, + + /// + /// Contains a count of the ignorable characters that appear before the significant characters of the message. + /// + PidTagRtfSyncPrefixCount = 0x1010, + + /// + /// Contains a count of the ignorable characters that appear after the significant characters of the message. + /// + PidTagRtfSyncTrailingCount = 0x1011, + + /// + /// The OrigEntryId + /// + OrigEntryId = 0x300F, + + /// + /// he MetaTagIdsetGiven property contains a serialization of REPLGUID-based IDSET structures, as specified in section 2.2.2.4.2. + /// + MetaTagIdsetGiven = 0x4017, + + /// + /// The MetaTagCnsetSeen property contains a serialization of REPLGUID-based CNSET structures, as specified in section 2.2.2.4. + /// + MetaTagCnsetSeen = 0x6796, + + /// + /// The MetaTagCnsetRead property contains a serialization of REPLGUID-based CNSET structures, as specified in section 2.2.2.4. + /// + MetaTagCnsetRead = 0x67D2, + + /// + /// The MetaTagCnsetSeenFAI property contains a serialization of REPLGUID-based IDSET structures, as specified in section 2.2.2.4. + /// + MetaTagCnsetSeenFAI = 0x67DA } /// diff --git a/MAPIInspector/Source/Utilities.cs b/MAPIInspector/Source/Utilities.cs index dae2144..05f2450 100644 --- a/MAPIInspector/Source/Utilities.cs +++ b/MAPIInspector/Source/Utilities.cs @@ -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[] 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) { @@ -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); } + + /// + /// Converts a simple (non-flag) enum to string. If the value is not present in the underlying enum, converts to a hex string. + /// + /// + /// + public static string EnumToString(object obj) + { + if (Enum.IsDefined(obj.GetType(), obj)) + { + return obj.ToString(); + } + else + { + return $"0x{Convert.ToUInt64(obj):X}"; + } + } } } \ No newline at end of file