From 7a885acb71458c6404aa307bd59039d4c6ddfbf7 Mon Sep 17 00:00:00 2001
From: Patrick Simpson
Date: Tue, 28 Feb 2017 14:02:52 +0100
Subject: [PATCH] 32-bit fixes for encoding of search criteria
---
.../AcaciaZPushPlugin/Native/MAPI/Property.cs | 11 +-
.../Native/MAPI/Restriction.cs | 123 ++++++++++--------
.../AcaciaZPushPlugin/Native/NativeEncoder.cs | 25 +++-
3 files changed, 91 insertions(+), 68 deletions(-)
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Native/MAPI/Property.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Native/MAPI/Property.cs
index 384c845..7a20d48 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Native/MAPI/Property.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Native/MAPI/Property.cs
@@ -66,8 +66,7 @@ namespace Acacia.Native.MAPI
}
}
- // TODO: align is probably wrong for 32-bit
- [StructLayout(LayoutKind.Sequential)]
+ [StructLayout(LayoutKind.Explicit)]
public struct PropValue
{
[StructLayout(LayoutKind.Sequential)]
@@ -124,7 +123,9 @@ namespace Acacia.Native.MAPI
// LONG x; /* case PT_NULL, PT_OBJECT (no usable value) */
}
+ [FieldOffset(0)]
public Header header;
+ [FieldOffset(8)]
public Data data;
public override string ToString()
@@ -160,13 +161,13 @@ namespace Acacia.Native.MAPI
return encoder.Allocate(obj.header, obj.data.b);
case PropType.STRING8:
IntPtr ptrA = encoder.Allocate(Encoding.ASCII.GetBytes((string)value), new byte[] { 0 });
- return encoder.Allocate(obj.header, ptrA);
+ return encoder.Allocate(obj.header, 8, ptrA);
case PropType.UNICODE:
IntPtr ptrW = encoder.Allocate(Encoding.Unicode.GetBytes((string)value), new byte[] { 0, 0 });
- return encoder.Allocate(obj.header, ptrW);
+ return encoder.Allocate(obj.header, 8, ptrW);
case PropType.BINARY:
obj.data.bin = ((SBinary)value).Marshal(encoder);
- return encoder.Allocate(obj.header, obj.data.bin);
+ return encoder.Allocate(obj.header, 8, obj.data.bin);
default:
throw new NotImplementedException();
}
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Native/MAPI/Restriction.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Native/MAPI/Restriction.cs
index d17eabf..23c70c3 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Native/MAPI/Restriction.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Native/MAPI/Restriction.cs
@@ -207,53 +207,62 @@ namespace Acacia.Native.MAPI
}
}
- // TODO: check this on 32 bit machines
- [StructLayout(LayoutKind.Explicit)]
+ [StructLayout(LayoutKind.Sequential)]
unsafe public struct SRestriction
{
- [FieldOffset(0)]
- public RestrictionType rt;
+ [StructLayout(LayoutKind.Sequential)]
+ public struct Header
+ {
+ public RestrictionType rt;
+ }
- // And/Or
- [FieldOffset(8)]
- public SubRestriction sub;
+ [StructLayout(LayoutKind.Explicit)]
+ unsafe public struct Data
+ {
+ // And/Or
+ [FieldOffset(0)]
+ public SubRestriction sub;
- [FieldOffset(8)]
- public NotRestriction not;
+ [FieldOffset(0)]
+ public NotRestriction not;
- [FieldOffset(8)]
- public ContentRestriction content;
+ [FieldOffset(0)]
+ public ContentRestriction content;
- [FieldOffset(8)]
- public PropertyRestriction prop;
+ [FieldOffset(0)]
+ public PropertyRestriction prop;
- [FieldOffset(8)]
- public BitMaskRestriction bitMask;
+ [FieldOffset(0)]
+ public BitMaskRestriction bitMask;
- [FieldOffset(8)]
- public ExistRestriction exist;
+ [FieldOffset(0)]
+ public ExistRestriction exist;
- [FieldOffset(8)]
- public CommentRestriction comment;
+ [FieldOffset(0)]
+ public CommentRestriction comment;
+ }
+
+ public Header header;
+ public Data data;
public SearchQuery ToSearchQuery()
{
- switch (rt)
+ switch (header.rt)
{
case RestrictionType.AND:
- return sub.ToSearchQuery(true);
+ return data.sub.ToSearchQuery(true);
case RestrictionType.OR:
- return sub.ToSearchQuery(false);
+ return data.sub.ToSearchQuery(false);
case RestrictionType.NOT:
- return not.ToSearchQuery();
+ return data.not.ToSearchQuery();
case RestrictionType.CONTENT:
- return content.ToSearchQuery();
+ return data.content.ToSearchQuery();
case RestrictionType.PROPERTY:
- return prop.ToSearchQuery();
+ return data.prop.ToSearchQuery();
case RestrictionType.BITMASK:
- return bitMask.ToSearchQuery();
+ return data.bitMask.ToSearchQuery();
case RestrictionType.EXIST:
- return exist.ToSearchQuery();
+ return data.exist.ToSearchQuery();
/* TODO COMPAREPROPS,
BITMASK,
@@ -275,27 +284,27 @@ namespace Acacia.Native.MAPI
public string ToString(int depth)
{
string indent = new string(' ', depth);
- string s = indent + rt.ToString() + "\n" + indent + "{\n";
- switch (rt)
+ string s = indent + header.rt.ToString() + "\n" + indent + "{\n";
+ switch (header.rt)
{
case RestrictionType.AND:
case RestrictionType.OR:
- s += sub.ToString(depth + 1);
+ s += data.sub.ToString(depth + 1);
break;
case RestrictionType.NOT:
- s += not.ToString(depth + 1);
+ s += data.not.ToString(depth + 1);
break;
case RestrictionType.CONTENT:
- s += content.ToString(depth + 1);
+ s += data.content.ToString(depth + 1);
break;
case RestrictionType.PROPERTY:
- s += prop.ToString(depth + 1);
+ s += data.prop.ToString(depth + 1);
break;
case RestrictionType.BITMASK:
- s += bitMask.ToString(depth + 1);
+ s += data.bitMask.ToString(depth + 1);
break;
case RestrictionType.EXIST:
- s += exist.ToString(depth + 1);
+ s += data.exist.ToString(depth + 1);
break;
/* TODO COMPAREPROPS,
@@ -361,15 +370,15 @@ namespace Acacia.Native.MAPI
public void Encode(SearchQuery.PropertyExists part)
{
- Current->rt = RestrictionType.EXIST;
- Current->exist.prop = part.Property.Tag;
+ Current->header.rt = RestrictionType.EXIST;
+ Current->data.exist.prop = part.Property.Tag;
}
public void Encode(SearchQuery.Or part)
{
- Current->rt = RestrictionType.OR;
- Current->sub.cb = (uint)part.Operands.Count;
- Current->sub.ptr = EncodePointer(part.Operands);
+ Current->header.rt = RestrictionType.OR;
+ Current->data.sub.cb = (uint)part.Operands.Count;
+ Current->data.sub.ptr = EncodePointer(part.Operands);
}
public void Encode(SearchQuery.PropertyIdentifier part)
@@ -380,15 +389,15 @@ namespace Acacia.Native.MAPI
public void Encode(SearchQuery.Not part)
{
- Current->rt = RestrictionType.NOT;
- Current->not.ptr = EncodePointer(new[] { part.Operand });
+ Current->header.rt = RestrictionType.NOT;
+ Current->data.not.ptr = EncodePointer(new[] { part.Operand });
}
public void Encode(SearchQuery.And part)
{
- Current->rt = RestrictionType.AND;
- Current->sub.cb = (uint)part.Operands.Count;
- Current->sub.ptr = EncodePointer(part.Operands);
+ Current->header.rt = RestrictionType.AND;
+ Current->data.sub.cb = (uint)part.Operands.Count;
+ Current->data.sub.ptr = EncodePointer(part.Operands);
}
private SRestriction* EncodePointer(IEnumerable operands)
@@ -425,26 +434,26 @@ namespace Acacia.Native.MAPI
public void Encode(SearchQuery.PropertyContent part)
{
- Current->rt = RestrictionType.CONTENT;
- Current->content.ulFuzzyLevel = ContentRestriction.FuzzyLevelFromSearchQuery(part);
- Current->content.ulPropTag = part.Property.Tag;
- Current->content.prop = (PropValue*)PropValue.MarshalFromObject(this, part.Property.Tag, part.Content);
+ Current->header.rt = RestrictionType.CONTENT;
+ Current->data.content.ulFuzzyLevel = ContentRestriction.FuzzyLevelFromSearchQuery(part);
+ Current->data.content.ulPropTag = part.Property.Tag;
+ Current->data.content.prop = (PropValue*)PropValue.MarshalFromObject(this, part.Property.Tag, part.Content);
}
public void Encode(SearchQuery.PropertyCompare part)
{
- Current->rt = RestrictionType.PROPERTY;
- Current->prop.relop = (SearchOperation)part.Operation;
- Current->prop.ulPropTag = part.Property.Tag;
- Current->prop.prop = (PropValue*)PropValue.MarshalFromObject(this, part.Property.Tag, part.Value);
+ Current->header.rt = RestrictionType.PROPERTY;
+ Current->data.prop.relop = (SearchOperation)part.Operation;
+ Current->data.prop.ulPropTag = part.Property.Tag;
+ Current->data.prop.prop = (PropValue*)PropValue.MarshalFromObject(this, part.Property.Tag, part.Value);
}
public void Encode(SearchQuery.PropertyBitMask part)
{
- Current->rt = RestrictionType.BITMASK;
- Current->bitMask.bmr = (BMR)(int)part.Operation;
- Current->bitMask.prop = part.Property.Tag;
- Current->bitMask.mask = part.Mask;
+ Current->header.rt = RestrictionType.BITMASK;
+ Current->data.bitMask.bmr = (BMR)(int)part.Operation;
+ Current->data.bitMask.prop = part.Property.Tag;
+ Current->data.bitMask.mask = part.Mask;
}
}
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Native/NativeEncoder.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Native/NativeEncoder.cs
index cf38e2a..1fe0ce5 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Native/NativeEncoder.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Native/NativeEncoder.cs
@@ -134,27 +134,40 @@ namespace Acacia.Native
int size = 0;
int[] starts = new int[all.Length];
+ object[] encode = new object[all.Length];
+ int used = 0;
+ int align = -1;
for (int i = 0; i < all.Length; ++i)
{
- starts[i] = Align(size);
+ if (all[i] is int)
+ {
+ align = (int)all[i];
+ ++i;
+ }
+
+ starts[used] = Align(size, align);
int thisSize = Marshal.SizeOf(all[i]);
- size = starts[i] + thisSize;
+ size = starts[used] + thisSize;
+ encode[used] = all[i];
+ align = -1;
+ ++used;
}
AllocationBase alloc = Allocate(size);
IntPtr ptr = alloc.Pointer;
- for (int i = 0; i < all.Length; ++i)
+ for (int i = 0; i < used; ++i)
{
- Marshal.StructureToPtr(all[i], ptr + starts[i], false);
+ Marshal.StructureToPtr(encode[i], ptr + starts[i], false);
}
return alloc.Pointer;
}
- private int Align(int size)
+ private int Align(int size, int align)
{
- int align = Marshal.SizeOf();
+ if (align < 0)
+ align = Marshal.SizeOf();
int additional = (align - (size % align)) % align;
return size + additional;
}