views:

181

answers:

2

I want to creating an addin that captures when a {contact, calendar, task, note} is {created, edited, removed}. I have the following code, to make it shorter I removed all the code but the related to contact, since all types will be the same I guess.

AutoSync.h

class ATL_NO_VTABLE AutoSync : 
 public wxPanel,
 public IDispEventSimpleImpl<1, AutoSync, &__uuidof(Outlook::ItemsEvents)>,
 public IDispEventSimpleImpl<2, AutoSync, &__uuidof(Outlook::ItemsEvents)>,
 public IDispEventSimpleImpl<3, AutoSync, &__uuidof(Outlook::ItemsEvents)>
{
public:
 AutoSync();
 ~AutoSync();

 void __stdcall OnItemAdd(IDispatch* Item); /* 0xf001 */
 void __stdcall OnItemChange(IDispatch* Item); /* 0xf002 */ 
 void __stdcall OnItemRemove(); /* 0xf003 */

 BEGIN_SINK_MAP(AutoSync)
  SINK_ENTRY_INFO(1, __uuidof(Outlook::ItemsEvents), 0xf001, OnItemAdd, &OnItemsAddInfo)
  SINK_ENTRY_INFO(2, __uuidof(Outlook::ItemsEvents), 0xf002, OnItemChange, &OnItemsChangeInfo)
  SINK_ENTRY_INFO(3, __uuidof(Outlook::ItemsEvents), 0xf003, OnItemRemove, &OnItemsRemoveInfo)
 END_SINK_MAP()

 typedef IDispEventSimpleImpl<1, AutoSync, &__uuidof(Outlook::ItemsEvents)> ItemAddEvents;
 typedef IDispEventSimpleImpl<2, AutoSync, &__uuidof(Outlook::ItemsEvents)> ItemChangeEvents;
 typedef IDispEventSimpleImpl<3, AutoSync, &__uuidof(Outlook::ItemsEvents)> ItemRemoveEvents;

    private:

    CComPtr<Outlook::_Items> m_contacts;

    };

AutoSync.cpp

 _NameSpacePtr pMAPI = OutlookWorker::GetInstance()->GetNameSpacePtr();


MAPIFolderPtr pContactsFolder = NULL;
 HRESULT hr = NULL;

 //get folders
 if(pMAPI != NULL) {
  pMAPI->GetDefaultFolder(olFolderContacts, &pContactsFolder);
 }

 //get items
 if(pContactsFolder != NULL) pContactsFolder->get_Items(&m_contacts);

 //dispatch events
 if(m_contacts != NULL) {
    //HERE COMES THE EXCEPTION
  hr = ItemAddEvents::DispEventAdvise((IDispatch*)m_contacts,&__uuidof(Outlook::ItemsEvents));
  hr = ItemChangeEvents::DispEventAdvise((IDispatch*)m_contacts,&__uuidof(Outlook::ItemsEvents));
  hr = ItemRemoveEvents::DispEventAdvise((IDispatch*)m_contacts,&__uuidof(Outlook::ItemsEvents));
 }

somewhere else defined:

extern _ATL_FUNC_INFO OnItemsAddInfo;
extern _ATL_FUNC_INFO OnItemsChangeInfo;
extern _ATL_FUNC_INFO OnItemsRemoveInfo;
_ATL_FUNC_INFO OnItemsAddInfo = {CC_STDCALL,VT_EMPTY,1,{VT_DISPATCH}};
_ATL_FUNC_INFO OnItemsChangeInfo = {CC_STDCALL,VT_EMPTY,1,{VT_DISPATCH}};
_ATL_FUNC_INFO OnItemsRemoveInfo = {CC_STDCALL,VT_EMPTY,0};

The problems comes in the

    hr = ItemAddEvents::DispEventAdvise((IDispatch*)m_contacts,&__uuidof(Outlook::ItemsEvents));
  hr = ItemChangeEvents::DispEventAdvise((IDispatch*)m_contacts,&__uuidof(Outlook::ItemsEvents));
  hr = ItemRemoveEvents::DispEventAdvise((IDispatch*)m_contacts,&__uuidof(Outlook::ItemsEvents));

It gives exception in 'atlbase.inl' when executes method 'Advise':

ATLINLINE ATLAPI AtlAdvise(IUnknown* pUnkCP, IUnknown* pUnk, const IID& iid, LPDWORD pdw)
{
 if(pUnkCP == NULL)
  return E_INVALIDARG;

 CComPtr<IConnectionPointContainer> pCPC;
 CComPtr<IConnectionPoint> pCP;
 HRESULT hRes = pUnkCP->QueryInterface(__uuidof(IConnectionPointContainer), (void**)&pCPC);
 if (SUCCEEDED(hRes))
  hRes = pCPC->FindConnectionPoint(iid, &pCP);
 if (SUCCEEDED(hRes))
    //HERE GIVES EXCEPTION
    //Unhandled exception at 0x2fe913e3 in OUTLOOK.EXE: 0xC0000005: 
    //Access violation reading location 0xcdcdcdcd.
  hRes = pCP->Advise(pUnk, pdw);
 return hRes;
}

I can't manage to understand why. Any sugestion here? Everything seems to be fine, but obviously is not. I've been stucked here for quite a long time. Need your help, thanks.

A: 

The first fact from a quick look is that you only need to derive from one IDispEventSimpleImpl per interface - you don't need one for every method in the interface:

class ATL_NO_VTABLE AutoSync : 
  public wxPanel,
  public IDispEventSimpleImpl<1, AutoSync, &__uuidof(Outlook::ItemsEvents)>
{
public:
  // ...
  BEGIN_SINK_MAP(AutoSync)
    SINK_ENTRY_INFO(1, __uuidof(Outlook::ItemsEvents), 0xf001, OnItemAdd, &OnItemsAddInfo)
    SINK_ENTRY_INFO(1, __uuidof(Outlook::ItemsEvents), 0xf002, OnItemChange, &OnItemsChangeInfo)
    SINK_ENTRY_INFO(1, __uuidof(Outlook::ItemsEvents), 0xf003, OnItemRemove, &OnItemsRemoveInfo)
  END_SINK_MAP()

  typedef IDispEventSimpleImpl<1, AutoSync, &__uuidof(Outlook::ItemsEvents)> ItemAddEvents;
  // ...
};

Try again with that simplification.

Georg Fritzsche
Simplification done, but still the very same exception. Any other idea?
framara
@framara: Not really without digging out a test project later. A random shot in the dark would be to test with the `wxPanel` removed.
Georg Fritzsche
wxPanel removed and not working, still same exception. Thank you anyway, I really appreciate it ;)
framara
I'm just giving random shots here. When debugging, -this -ATL::IDispEventSimpleImpl<...> -ATL::_IDispEventLocator<...> -ATL::_IDispEvent +__vfptr 0xcdcdcdcd +m_libid {GUID_NULL} +m_iid {GUID_NULL} m_wMayorVerNum 0x0000 m_wMinorVerNum 0x0000 m_dwEventCookie 0xfefefefeMaybe it has nothing to do at all but, it looks a bit weird/bad to me no?edit: I uploaded a pic since the formating of the comment is a bit complicated, http://yfrog.com/2sdebugj
framara
Weird, but could be the debugger as well as some corruption. Can't really look into it before the weekend i think, sadly its no quick process to get a fresh test-project set up for Outlook Addins. There is also a [newsgroup](http://groups.google.com/group/microsoft.public.office.developer.com.add_ins/) (but there wasn't much feedback for C++/ATL specifics *afair*) and maybe there is more activity in the MSDN social forums?
Georg Fritzsche
I've tried in both and there's no answer. The thing is that the code look pretty good (I think) so I can't get where that exception is coming from... This is driving me crazy
framara
A: 

I had a similar problem, the reason was I was calling virtual methods from within the constructor. If your code in question is in the constructor, try moving it to FinalConstruct().

haimg