Monday, March 29, 2004 5:43 PM
by
gorlach
MAPILogonEx and MAPISession object
How many MAPISession objects do you know? I know four different objects, they are live in MSMAPI32.DLL, but have different v-table addresses.
Lets take Outlook Inbox entry ID through object model (this code is the part of Outlook add-in):
CComPtr ns;
BYTE eid[100];
ULONG cb = 0;
if (SUCCEEDED(outlook->get_Session(&ns)))
{
CComPtr folder;
if (SUCCEEDED(ns->GetDefaultFolder(olFolderInbox,&folder)))
{
CComBSTR bstrEid;
if (SUCCEEDED(folder->get_EntryID(&bstrEid)))
{
CW2CT strEid(bstrEid);
if (FBinFromHex(strEid.m_psz,eid))
{
cb = (ULONG)strlen(strEid.m_psz)/2;
}
Ok. Now you can get MAPIOBJECT property of Outlook::_NameSpace object (yes, you'll get IMAPISession object). Pass the object to this function and you'll get the folder name:
HRESULT GetFolderName(IMAPISession* session, ULONG cb,
LPENTRYID eid, char* name)
{
IMAPIFolder *folder = NULL;
ULONG type;
HRESULT hr;
if (SUCCEEDED(hr=session->OpenEntry(cb,eid,
NULL,MAPI_BEST_ACCESS,&type,(LPUNKNOWN*)&folder)))
{
LPSPropValue val;
if (SUCCEEDED(hr=HrGetOneProp(folder,
PR_DISPLAY_NAME,&val)))
{
strcpy(name,val->Value.lpszA);
MAPIFreeBuffer(val);
}
}
return hr;
}
Fine. But Outlook 2000 have no MAPIOBJECT property in Outlook::_NameSpace.
Solution? Yes. We can call MAPILogonEx. Note, that we call it from Outlook add-in code, inside of OUTLOOK.EXE process.... Pass it to GetFolderName function and you'll get 0x80040201 error (unknown entry ID).
Interesting? Yes (and don't forget vote for us!!!). Because MAPIOBJECT property and MAPILogonEx are return different objects in all Outlooks. In Outlook 2003 corresponding v-table addresses are 0x360143d0 and 0x360a65b8.
How can you get "good and functional" MAPISession object in Outlook 2000? I have found only one legal way: you should create Exchange Extension instead of Outlook add-in. Exchange Extension receive "good" object pointer on loading.
I have also research about illegal ways. Yes, I have find it: undocumented function HrCreateNewWrappedObject from MSMAPI32.DLL. You can pass "bad" object and get back "good" object:
typedef HRESULT (WINAPI *HrCreateNewWrappedObjectFn) \
(IUnknown *obj, DWORD f1, DWORD f2, REFIID iid, \
DWORD f3, DWORD f4, IUnknown **out);
IMAPISession *bads, *goods;
...
HrCreateNewWrappedObjectFn fn = \
(HrCreateNewWrappedObjectFn)GetProcAddress(
LoadLibrary("MSMAPI32.DLL"),
"HrCreateNewWrappedObject@28");
if (fn)
{
hr = fn(bads,0x0e,1,IID_IMAPISession,0,0,&goods);
}
f1..f4 are currently unkown for me (I take the values from debugger), but I hope to research this topic at end of this week. This code is work fine inside Outlook 2003 add-in.