(MAPI)尝试从PR_EMS_AB_PROXY_ADDRESSES获取SMTP地址时出现算术溢出

时间:2013-08-18 16:18:23

标签: c# outlook marshalling mapi

所以我试图使用上面的属性获取SMTP地址属性。但是我得到算术溢出。

基本上我正在使用:

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);               

我创建的结构是:

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

我认为问题在于结构: http://msdn.microsoft.com/en-us/library/bb415341.aspx

问题是,propValue.Value真的是“长”,它不适合IntPtr,我认为该结构实际​​上是SPropValue结构的指针,

所以我不确定如何使用它以及如何解决问题。

任何帮助都会得到满足......

**编辑** 我试图创建一个联合PV类,从c ++这是联合类:

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 */  
...
...

所以我创建了这个结构:

      [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 */
 ....

现在我得到了垃圾值..

2 个答案:

答案 0 :(得分:0)

SPropValue.value结构是一个联合,这意味着成员彼此重叠。

为什么不使用AddressEntry.PropertyAccessor.GetProperty来检索属性?

答案 1 :(得分:0)

所以我设法解决了!我会解释一下。 值实际上是联合类型,我确实找到了正确的内存区域,但读错了。

当我们读到这段记忆时,我们有以下几点:

  • uint表示“值”类型和命令,我将其分为2个ushorts(第一个 - 更高的位是返回的类型:PT_MV_TSTRINGS,它等于MV_FLAGS | PT_UNICODE(多值+ unicode字符串)
  • uint of dwAlignedPad
  • SWStringArray - 这是实际的“值”,它具有数组长度的uint,后跟uint实际的字符串数组(指向数组指针的指针)

所以我创建了以下结构并将HrGetOneProp读入:

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
  }

所以在元帅之后

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

我创建了一个具有正确长度的指针数组来保存指向字符串的指针:

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

然后我有结构中字符串数组的内存地址,所以我将指针复制到我刚刚创建的数组中:

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

现在我有每个字符串的内存地址数组,现在只需将其编组为字符串:

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

顺便说一下,字符串数组有两个可能的值: (http://msdn.microsoft.com/en-us/library/bb446176.aspx

  • PT_MV_STRING8 - SLPSTRArray
  • PT_MV_UNICODE - SWStringArray

所以我添加了一个支票(针对PropType) - 应该是MV_FLAG | ANSI字符串的PT_STRING8和MV_FLAG | PT_UNICODE用于unicode,然后使用正确的MarshalPtrToStringAnsi / Uni

我需要检查的几个问题:

    64位Outlook中的
  1. - 这段代码好吗?或者我必须以不同的方式处理
  2. 检查每个展望版本(2003,2007,2010,2010 64位)