(MAPI) getting arithmetic overflow when trying to get SMTP address from PR_EMS_AB_PROXY_ADDRESSES

StackOverflow https://stackoverflow.com/questions/18301175

  •  24-06-2022
  •  | 
  •  

Question

so i'm trying to get the SMTP address property using the above property. but i get arithmetic overflow.

basicly im using:

IUnknown = Marshal.GetIUnknownForObject(recipientAddress.MAPIOBJECT);
HrGetOneProp(IMAPIProperty, PR_EMS_AB_PROXY_ADDRESSES, ref pPropValue);
SPropValue propValue = (SPropValue)Marshal.PtrToStructure(pPropValue, typeof(SPropValue));
IntPtr ptrToConvert = new IntPtr(propValue.Value); //arithmetic overflow
sProperty = Marshal.PtrToStringAnsi(ptrToConvert);               

the structure i created was:

private struct SPropValue {
public unit ulPropTag
public uint dwAlignPad
public long Value
} 

i think that the problem is with the structure: http://msdn.microsoft.com/en-us/library/bb415341.aspx

The issue is, that the propValue.Value is really "long", which doesnt fit into the IntPtr, and i think that the structure is actually a pointer of SPropValue structs,

so i'm not really sure how to use it and how to solve the issue.

Any help would be appriciated...

** EDIT ** i tried to create a union PV class, from c++ this is the union class:

typedef union _PV
{
short int           i;          /* case PT_I2 */
LONG                l;          /* case PT_LONG */
ULONG               ul;         /* alias for PT_LONG */
float               flt;        /* case PT_R4 */
double              dbl;        /* case PT_DOUBLE */
unsigned short int  b;          /* case PT_BOOLEAN */
CURRENCY            cur;        /* case PT_CURRENCY */
double              at;         /* case PT_APPTIME */
FILETIME            ft;         /* case PT_SYSTIME */  
...
...

so i created this struct:

      [StructLayout(LayoutKind.Explicit)]
  private struct PV_Union
  {
        [FieldOffset(0)]
        public Int16            i;          /* case PT_I2 */
     [FieldOffset(0)]
         public Int32               l;          /* case PT_LONG */
     [FieldOffset(0)]
         public UInt32              ul;         /* alias for PT_LONG */
 ....

now i get junk values..

Was it helpful?

Solution 2

so i managed to solve it! i'll explain. the Value is really union type, and i did get to the correct memory area but have read it wrong.

when we read this area of memory, we have the following:

  • uint that represents the "Value" type and the command, i divided it into 2 ushorts (the first one - which is the higher bits is the returned type: PT_MV_TSTRINGS which is equal to MV_FLAGS|PT_UNICODE (multivalued + unicode string)
  • uint of dwAlignedPad
  • SWStringArray - which is the actual "Value", which has uint of the the array length, and followed by uint of the actual strings array (pointer to an array pointer)

so i created the following struct and read the HrGetOneProp into this:

private struct SMultivalueStructure
  {
     public ushort PropType; // Type of returned value
     public ushort Command; //Command we entered (PR_EMS_PROXY...)
     public uint dwAlignPad; // Reserved - usually 4 bytes of 0
     public uint stringArrayLength; // SWStringArray length
     public uint pStringArrayMemoryAddress; //SWStringArray pointer to string array
  }

so after the marshal

SMultivalueStructure propValue = (SMultivalueStructure)Marshal.PtrToStructure(pPropValue, typeof(SMultivalueStructure));

i created a pointer array with the correct length to hold the pointers to the strings:

IntPtr[] pStrings = new IntPtr[propValue.stringArrayLength];

then i have the memory address of the strings array in the struct, so i will copy the pointers into the array i just created:

Marshal.Copy(new IntPtr(propValue.pStringArrayMemoryAddress), pStrings, 0, (int)propValue.stringArrayLength);

now i have array of the memory addresses for each string, now just marshal it to string:

for (int i = 0; i < pStrings.Length; ++i)
   {
        string smtpTest = Marshal.PtrToStringAnsi(pStrings[i]);
   }

by the way, there are 2 possible values that the string array can be: (http://msdn.microsoft.com/en-us/library/bb446176.aspx)

  • PT_MV_STRING8 - SLPSTRArray
  • PT_MV_UNICODE - SWStringArray

so i added a check (against PropType) - should be MV_FLAG | PT_STRING8 for ANSI string, and MV_FLAG | PT_UNICODE for unicode, then used the correct MarshalPtrToStringAnsi / Uni

few issues i need to check:

  1. in 64 bit outlook - is this code ok? or do i have to handle that differently
  2. check that for every outlook version (2003,2007,2010,2010 64 bit)

OTHER TIPS

SPropValue.value structure is a union, which means the members overlap each other.

Why not use AddressEntry.PropertyAccessor.GetProperty to retrieve the property?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top