Chinaunix首页 | 论坛 | 博客
  • 博客访问: 231625
  • 博文数量: 68
  • 博客积分: 2010
  • 博客等级: 大尉
  • 技术积分: 612
  • 用 户 组: 普通用户
  • 注册时间: 2007-01-04 22:38
文章分类

全部博文(68)

文章存档

2010年(2)

2009年(12)

2008年(54)

我的朋友

分类:

2008-12-13 11:23:08

AdviseSink对于我们了解系统SMS以及OUTLOOK的消息运作有很大帮助,我们可以挂接到SMSOUTLOOKMessage Store上,看看在做某些操作时,系统到底对Message做了些什么。下面我举个一个例子来说明它的用途:

不知道大家有没有注意,在Smartphone上的Deleted Box里面有个按钮叫Restore,即恢复功能,如果是你用系统菜单把一条Message删除到Deleted Box的话,Restore可以正常工作,但是如果你用MAPI去操作呢?比如IMAPIFolder::CopyMessages你可以试一下,这个时候Restore失效了,由此可见系统在用菜单删除Message的时候自己做了些手脚,那我们怎么知道它具体做了哪些事情呢?这个时候IMAPIAdviseSink就派上用场了,不过在这之前先简要介绍一下MAPI属性,我们可以看一下mapitags.h中关于属性的定义,非常明显,一个属性由类型和ID两个部分通过PROP_TAG宏作用生成。类型代表这个属性的值是以什么形式存放在数据库里面的,这关系到你能否正确读写该属性,比如我们在调用IMessage:: GetProps时候,返回了结构体SPropValue

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

         LPSTR               lpszA;      /* case PT_STRING8 */

         SBinary             bin;        /* case PT_BINARY */

         LPWSTR              lpszW;      /* case PT_UNICODE */

         LPGUID              lpguid;     /* case PT_CLSID */

         …….

     } __UPV;

 

     typedef struct _SPropValue

     {

         ULONG       ulPropTag;

         ULONG       dwAlignPad;

     union _PV   Value;

} SPropValue, FAR * LPSPropValue;

看到union _PV了吗,我们如何知道该取哪个值来用呢?这就得通过属性的类型来告诉我们了,我们可以通过宏PROP_TYPE来获取一个属性的类型,通过PROP_ID来获取ID

 

好了,下面是OnNotify实现:

     ULONG CAdviseSink::OnNotify(ULONG cNotif, LPNOTIFICATION lpNotifications)

     {       

          if(cNotif > 0 && NULL != lpNotifications)

          {

              for(int i = 0; i < (int)cNotif; ++i)

              {

                   switch(lpNotifications[i].ulEventType)

                   {

                       //Message 发生了改变,这时lpNotifications[i].info.obj.lpPropTagArray就代表了发生改变的属性值列表。

                       case fnevObjectModified:

                       {

                            // iPropCount : 表示一共有多少个属性发生了改变

                            int iPropCount         = lpNotifications[i].info.obj.lpPropTagArray->cValues;

                            for(int j = 0; j < iPropCount; j++)

                            {

                                 // ulPropType : 属性类型,即PT_LONGPT_DOUBLEPT_BINARY等等,定义可以在mapidefs.h里面找到

                                 // ulPropID :   属性ID,可以在mapitags.h里面找到

                                 // 在此处打上断点或者打上日志,我们就可以知道在系统删除Message时,对它到底做了什么。

                                 ULONG ulPropType        = PROP_TYPE(lpNotifications[i].info.obj.lpPropTagArray->aulPropTag[j]);

                                 ULONG ulPropID         = PROP_ID(lpNotifications[i].info.obj.lpPropTagArray->aulPropTag[j]);                            }

                            break;

                        }

                       default:

                            break;                

                   }

               }

          }   

          return 0;

}

 

     按照上一篇介绍的方法,把它挂到SMS Store上,启动调试状态,等待Modified事件发生。然后到系统收件箱中创建一条新的SMS,并且删除它,前面新建时的通知我们不关心,当删除时OnNotify一共会收到3次通知消息,认真观察,第一次类型为3(PT_LONG)ID13827(PR_CONTENT_UNREAD),第二次也一样,第三次呢,类型为258(PT_BINARY),ID34072,恩?这并不是标准的属性,从SDK上看从0x80000xFFFE应该是用户自定义属性区域,可见这是MS在实现SMS程序时自己添加的一个属性,做什么用呢?类型是PT_BINARY,会不会是这条Message原始所在BoxEntryID呢?把它的数据打印出来和Draft BoxEntryID一比较,果然一模一样,这下明白了,MS在这里做了个手脚,在它自己的程序里面删除MESSAGE时,会添加一个自定义的属性,并把MESSAGE原始所在BOXEntryID写进去,等到点Restore时,就读取这个值,把MESSAGE恢复回去,我们利用MAPI操作的MESSAGE没有置这个属性,当然不起作用了,所以我们所要做的只是在CopyMessage之前,把这个属性写上而已,这时再试一把,OK,搞定。

     这只是一个简单的例子,AdviseSink对于平时对MAPI的调试很有帮助,从注册时的那一堆标志就可以看出,它不仅仅是用来监视Message而已,功能还是很强大的,不过我个人对其他功能倒没有很深入的研究,就不做介绍了,如果有朋友做过类似方面的研究,请告知我下,也让我学习一下。

OK,今天先写到这里,下篇将继续讨论IMAPIAdviseSink,主要是讲如何在OnNotify中取得被改变的Message对象。

阅读(880) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~