2025-04-27 07:49:33 -04:00

1052 lines
27 KiB
C++

/*
Copyright (c) 2000 Microsoft Corporation
Module Name:
smapi.cpp
Abstract:
CSMapi object. Used to support our simple MAPI functions.
Revision History:
created steveshi 08/23/00
*/
#include "stdafx.h"
#include "Rcbdyctl.h"
#include "smapi.h"
#include "Recipient.h"
#include "Recipients.h"
#include "mapix.h"
#include "utils.h"
#define C_OEAPP TEXT("Outlook Express")
#define F_ISOE 0x1
#define F_ISCONFIG 0x2
#define LEN_MSOE_DLL 9 // length of "\\msoe.dll"
#define LEN_HMMAPI_DLL 11 // length of "\\hmmapi.dll"
BOOL GetMAPIDefaultProfile(TCHAR*, DWORD*);
#define E_FUNC_NOTFOUND 1000 //Userdefined error no.
#define MACRO_AddRecipientInternal( pName ) \
{ \
CComObject<Recipient>* pItem = NULL; \
HRESULT hr = CComObject<Recipient>::CreateInstance(&pItem); \
if (hr) \
goto done; \
pItem->AddRef(); \
pItem->put_Name(CComBSTR(pName).Copy()); \
((Recipient*)pItem)->m_pNext = m_pRecipHead; \
m_pRecipHead = (Recipient*)pItem; \
done: \
return hr; \
}
// Csmapi
Csmapi::~Csmapi()
{
if (m_bLogonOK)
Logoff();
if (m_hLib)
FreeLibrary(m_hLib);
}
STDMETHODIMP Csmapi::InterfaceSupportsErrorInfo(REFIID riid)
{
static const IID* arr[] =
{
&IID_Ismapi
};
for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
if (InlineIsEqualGUID(*arr[i],riid))
return S_OK;
}
return S_FALSE;
}
BOOL Csmapi::IsOEConfig()
{
CRegKey cOE;
LONG lRet;
BOOL bRet = FALSE;
TCHAR szBuf[MAX_PATH];
DWORD dwCount = MAX_PATH -1 ;
lRet = cOE.Open(HKEY_CURRENT_USER, TEXT("Software\\Microsoft\\Internet Account Manager"), KEY_READ);
if(lRet == ERROR_SUCCESS)
{
lRet = cOE.QueryValue(szBuf, TEXT("Default Mail Account"), &dwCount);
if (lRet == ERROR_SUCCESS)
{
TCHAR szActs[MAX_PATH];
CRegKey cOEAcct;
wsprintf(szActs, TEXT("Accounts\\%s"), szBuf);
lRet = cOEAcct.Open((HKEY)cOE, szActs, KEY_READ);
if (lRet == ERROR_SUCCESS)
{
bRet = TRUE;
cOEAcct.Close();
}
}
cOE.Close();
}
return bRet;
}
STDMETHODIMP Csmapi::get_Reload(LONG* pVal)
{
HRESULT hr = S_OK;
CComBSTR bstrName, bstrOldName;
*pVal = 0; // assume failed for some reason;
if(m_bLogonOK)
{
Logoff();
}
if (m_hLib)
{
FreeLibrary(m_hLib);
m_lpfnMapiFreeBuf = NULL;
m_lpfnMapiAddress = NULL;
m_hLib = NULL;
}
if (m_szSmapiName[0] != _T('\0'))
bstrOldName = m_szSmapiName;
m_lOEFlag = 0;
hr = get_SMAPIClientName(&bstrName);
if (FAILED(hr) || bstrName.Length() == 0)
{
*pVal = 0; // failed for some reason
goto done;
}
if (bstrOldName.Length() > 0 && wcscmp(bstrOldName,bstrName) != 0)
{
*pVal = 1; // Email client get changed.
}
else
{
*pVal = -1; // succeed.
}
done:
return S_OK;
}
STDMETHODIMP Csmapi::get_SMAPIClientName(BSTR *pVal)
{
HRESULT hr = S_OK;
CRegKey cKey;
LONG lRet;
DWORD dwCount = sizeof(m_szSmapiName)/sizeof(m_szSmapiName[0]) -1;
// Get default email client
if (m_hLib) // Already initialized.
goto done;
#ifndef _WIN64 // WIN32. We use only OE on Win64.
lRet = cKey.Open(HKEY_LOCAL_MACHINE, TEXT("Software\\Clients\\Mail"), KEY_READ);
if (lRet != ERROR_SUCCESS)
goto done;
lRet = cKey.QueryValue(m_szSmapiName, NULL, &dwCount); // get default value
if (lRet == ERROR_SUCCESS)
{
// Is the email client Smapi compliant?
// 1. get it's dllpath
CRegKey cMail;
lRet = cMail.Open((HKEY)cKey, m_szSmapiName, KEY_READ);
if (lRet == ERROR_SUCCESS)
{
dwCount = sizeof(m_szDllPath)/sizeof(m_szDllPath[0]) - 1;
lRet = cMail.QueryValue(m_szDllPath, TEXT("DLLPath"), &dwCount);
if (lRet == ERROR_SUCCESS)
{
LONG len = lstrlen(m_szDllPath);
if ( !(len > LEN_MSOE_DLL && // no need to check OE
lstrcmpi(&m_szDllPath[len - LEN_MSOE_DLL], TEXT("\\msoe.dll")) == 0) &&
!(len > LEN_HMMAPI_DLL && // We don't want HMMAPI either
_tcsicmp(&m_szDllPath[len - LEN_HMMAPI_DLL], TEXT("\\hmmapi.dll")) == 0))
{
HMODULE hLib = LoadLibrary(m_szDllPath);
if (hLib != NULL)
{
if (GetProcAddress(hLib, "MAPILogon"))
{
m_hLib = hLib; // OK, this is the email program that we want.
}
}
}
cMail.Close();
}
}
cKey.Close();
}
#endif
if (m_hLib == NULL) // Need to use OE
{
m_szSmapiName[0] = TEXT('\0'); // in case OE is not available.
m_hLib = LoadOE();
}
done:
*pVal = (BSTR)CComBSTR(m_szSmapiName).Copy();
return hr;
}
HMODULE Csmapi::LoadOE()
{
LONG lRet;
HKEY hKey, hSubKey;
DWORD dwIndex = 0;
TCHAR szName[MAX_PATH];
TCHAR szBuf[MAX_PATH];
TCHAR szDll[MAX_PATH];
DWORD dwName, dwBuf;
FILETIME ft;
HMODULE hLib = NULL;
lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
TEXT("Software\\Clients\\Mail"),
0,
KEY_ENUMERATE_SUB_KEYS,
&hKey);
if (lRet == ERROR_SUCCESS)
{
dwName = sizeof(szName) / sizeof(szName[0]);
while(ERROR_SUCCESS == RegEnumKeyEx(hKey,
dwIndex++, // subkey index
&szName[0], // subkey name
&dwName, // size of subkey buffer
NULL,
NULL,
NULL,
&ft))
{
// get dll path.
lRet = RegOpenKeyEx(hKey, szName, 0, KEY_QUERY_VALUE, &hSubKey);
if (lRet == ERROR_SUCCESS)
{
dwBuf = sizeof(szBuf);
lRet = RegQueryValueEx(hSubKey, // handle to key
TEXT("DllPath"),
NULL,
NULL,
(BYTE*)&szBuf[0], // data buffer
&dwBuf);
if (lRet == ERROR_SUCCESS)
{
// is it msoe.dll?
lRet = lstrlen(szBuf);
if (lRet > LEN_MSOE_DLL &&
lstrcmpi(&szBuf[lRet - LEN_MSOE_DLL], TEXT("\\msoe.dll")) == 0)
{
// Resolve environment variable.
lRet = sizeof(m_szDllPath) / sizeof(m_szDllPath[0]);
dwBuf = ExpandEnvironmentStrings(szBuf, m_szDllPath, lRet);
if (dwBuf > (DWORD)lRet)
{
// TODO: Need to handle this case
}
else if (dwBuf == 0)
{
// TODO: Failed.
}
else if ((hLib = LoadLibrary(m_szDllPath)))
{
lstrcpy(m_szSmapiName, szName);
m_lOEFlag = F_ISOE | (IsOEConfig() ? F_ISCONFIG : 0);
}
break;
}
}
RegCloseKey(hSubKey);
}
dwName = sizeof(szName) / sizeof(szName[0]);
}
RegCloseKey(hKey);
}
return hLib;
}
STDMETHODIMP Csmapi::get_IsSMAPIClient_OE(LONG *pVal)
{
HRESULT hr = S_OK;
CComBSTR bstrTest;
get_SMAPIClientName(&bstrTest);
*pVal = m_lOEFlag;
return hr;
}
/******************************************
Func:
Logon
Abstract:
Simple MAPI logon wrapper
Params:
None
*******************************************/
STDMETHODIMP Csmapi::Logon(ULONG *plReg)
{
HRESULT hr = E_FAIL;
*plReg = 0;
USES_CONVERSION;
ULONG err = 0;
// Check Win.ini MAPI == 1 ?
if (m_bLogonOK)
{
hr = S_OK;
*plReg = 0;
goto done;
}
// Load MAPI32.DLL
if (!m_hLib)
{
LONG lError;
get_Reload(&lError);
if (lError == 0) // failed.
{
*plReg = 1;
goto done;
}
}
if (m_hLib != NULL)
{
LPMAPILOGON lpfnMapiLogon = (LPMAPILOGON)GetProcAddress(m_hLib, "MAPILogon");
if (lpfnMapiLogon == NULL)
goto done;
// 1st, is there any existing session that I can use?
err = lpfnMapiLogon(
0L,
NULL,
NULL,
0 ,
0,
&m_lhSession);
if (err != SUCCESS_SUCCESS)
{
// OK. I need a new session.
// Get default profile from registry
//
TCHAR szProfile[256];
DWORD dwCount = 255;
szProfile[0]= TEXT('\0');
::GetMAPIDefaultProfile((TCHAR*)szProfile, &dwCount);
err = lpfnMapiLogon(
0L,
T2A(szProfile),
NULL,
MAPI_LOGON_UI ,
0,
&m_lhSession);
if (err != SUCCESS_SUCCESS)
{
PopulateAndThrowErrorInfo(err);
goto done;
}
}
// err == SUCCESS_SUCCESS
m_bLogonOK = TRUE;
*plReg = 1;
hr = S_OK;
}
done:
return hr;
}
/******************************************
Func:
Logoff
Abstract:
Simple MAPI logoff wrapper
Params:
*******************************************/
STDMETHODIMP Csmapi::Logoff()
{
// Clean up Recipient list
ClearRecipList();
if (m_bLogonOK)
{
LPMAPILOGOFF lpfnMapiLogOff = (LPMAPILOGOFF)GetProcAddress(m_hLib, "MAPILogoff");
if (lpfnMapiLogOff)
lpfnMapiLogOff (m_lhSession, 0, 0, 0);
m_bLogonOK = FALSE;
}
return S_OK;
}
/******************************************
Func:
OpenAddressBox
Abstract:
Simple MAPI MAPIAddress wrapper.
If the internal recepient list is not empty, it needs to generate a MapiRecipDesc and
pre-filled the address box.
Params:
*******************************************/
STDMETHODIMP Csmapi::OpenAddressBox()
{
HRESULT hr = E_FAIL;
ULONG lRet = 0;
if (!m_lpfnMapiAddress)
{
m_lpfnMapiAddress = (LPMAPIADDRESS)GetProcAddress(m_hLib, "MAPIAddress");
if (!m_lpfnMapiAddress) // No MAPIAddress?
return E_FAIL;
}
USES_CONVERSION;
if (m_bLogonOK)
{
ULONG lNewRecips = 0;
MapiRecipDesc *pOldMapiRecipDesc = NULL;
MapiRecipDesc *pNewRecips = NULL;
ULONG nRecips = 0;
// Is the name string not empty?
// If not, we need to generate a MapiRecipDesc for OpenAddress to display.
nRecips = GetRecipCount();
if (nRecips>0)
{
pOldMapiRecipDesc = new MapiRecipDesc[nRecips];
if (pOldMapiRecipDesc == NULL)
return E_OUTOFMEMORY;
ZeroMemory(pOldMapiRecipDesc, sizeof(MapiRecipDesc) * nRecips);
nRecips = 0;
for (Recipient* p=m_pRecipHead; p; p=p->m_pNext)
{
(pOldMapiRecipDesc)[nRecips].lpszName = W2A(p->m_bstrName);
(pOldMapiRecipDesc)[nRecips].ulRecipClass = MAPI_TO;
nRecips++;
}
}
lRet = m_lpfnMapiAddress(m_lhSession,
0,
NULL,
1,
NULL,
nRecips,
pOldMapiRecipDesc,
0,
0,
&lNewRecips,
&pNewRecips);
if (lRet == SUCCESS_SUCCESS)
{
// clean up old recipients for the new name list.
ClearRecipList();
for (int i=0; i< (int)lNewRecips; i++)
{
AddRecipientInternal(pNewRecips[i].lpszName);
}
// Free the returned buffer, since we don't need it.
if (pNewRecips)
MAPIFreeBuffer(pNewRecips);
hr = S_OK;
}
else if (lRet == MAPI_E_USER_ABORT)
{
hr = S_FALSE;
}
else
{
PopulateAndThrowErrorInfo(lRet);
}
if (pOldMapiRecipDesc)
delete pOldMapiRecipDesc;
}
return hr;
}
/******************************************
Func:
AddRecipient
Abstract:
Add new recipients to the recipient list.
Params:
newRecip: new recipient names. Seperate by ";".
*******************************************/
STDMETHODIMP Csmapi::AddRecipient(BSTR newRecip)
{
HRESULT hr = S_OK;
ULONG iCount;
WCHAR* pNew;
// Need to parse strings if users use multi names here.
if (!newRecip || (iCount = wcslen((WCHAR*)newRecip))==0)
return S_FALSE;
pNew = new WCHAR[iCount + 1];
if (pNew == NULL)
return E_OUTOFMEMORY;
wcscpy(pNew, (WCHAR*)newRecip);
WCHAR *p = pNew;
WCHAR *p1;
BOOL bEnd = FALSE;
// Parse names
while (1)
{
// Remove leading space
while ((*p == L' ' || *p == L';') && *p != L'\0')
p++;
if (*p == L'\0')
break;
p1=p++;
// Find end point
while (*p != L';' && *p != L'\0')
p++;
if (*p == L'\0')
bEnd = TRUE;
else
*p = L'\0'; // Create the end point of the current name string
hr = AddRecipientInternal(p1);
if (hr)
goto done;
if (bEnd)
break;
p++;
}
done:
if (pNew)
delete pNew;
return hr;
}
/******************************************
Func:
ClearRecipList
Abstract:
Remote the recipient list.
Params:
*******************************************/
STDMETHODIMP Csmapi::ClearRecipList()
{
while (m_pRecipHead)
{
Recipient* p = m_pRecipHead->m_pNext;
if (m_pRecipHead->m_pRecip)
MAPIFreeBuffer(m_pRecipHead->m_pRecip);
m_pRecipHead->Release();
m_pRecipHead = p;
}
return S_OK;
}
/******************************************
Func:
SendMail
Abstract:
Simple MAPI MAPISendMail wrapper. It always take the attachment file from m_bstrXMLFile member variable.
Params:
*plStatus: 1(Succeed)/others(Fail)
*******************************************/
STDMETHODIMP Csmapi::SendMail(LONG* plStatus)
{
HRESULT hr = E_FAIL;
ULONG err = 0;
ULONG cRecip = 0;
MapiRecipDesc *pMapiRecipDesc = NULL;
USES_CONVERSION;
*plStatus = 0;
if (!m_bLogonOK) // Logon problem !
return S_FALSE;
LPMAPISENDMAIL lpfnMapiSendMail = (LPMAPISENDMAIL)GetProcAddress(m_hLib, "MAPISendMail");
if (lpfnMapiSendMail == NULL)
return E_FAIL;
// Since we don't resolve name before, we need to resolve name here
// Even if the name list comes form AddressBook, some name list was not resolved
// in address book.
cRecip = BuildMapiRecipDesc(&pMapiRecipDesc);
if (cRecip <= 0 || pMapiRecipDesc == NULL)
{
if (cRecip == -1) // resolve name failed.
*plStatus = 2;
return E_FAIL;
}
MapiFileDesc attachment = {0, // ulReserved, must be 0
0, // no flags; this is a data file
(ULONG)-1, // position not specified
W2A(m_bstrXMLFile), // pathname
NULL, //"RcBuddy.MsRcIncident", // original filename
NULL}; // MapiFileTagExt unused
// Create a blank message. Most members are set to NULL or 0 because
// MAPISendMail will let the user set them.
MapiMessage note = {0, // reserved, must be 0
W2A(m_bstrSubject),
W2A(m_bstrBody),
NULL, // NULL = interpersonal message
NULL, // no date; MAPISendMail ignores it
NULL, // no conversation ID
0, // no flags, MAPISendMail ignores it
NULL, // no originator, this is ignored too
cRecip, // # of recipients
pMapiRecipDesc, // recipient array
1, // one attachment
&attachment}; // the attachment structure
//Next, the client calls the MAPISendMail function and
//stores the return status so it can detect whether the call succeeded.
err = lpfnMapiSendMail (m_lhSession, // use implicit session.
0L, // ulUIParam; 0 is always valid
&note, // the message being sent
0, // Use MapiMessge recipients
0L); // reserved; must be 0
if (err == SUCCESS_SUCCESS )
{
*plStatus = 1;
hr = S_OK;
}
else
{
PopulateAndThrowErrorInfo(err);
}
// remove array allocated inside BuildMapiRecipDesc with 'new' command
if (pMapiRecipDesc)
delete pMapiRecipDesc;
return hr;
}
/******************************************
Func:
get_Recipients
Abstract:
Return the Recipients list object.
Params:
*ppVal: Recipients object
*******************************************/
STDMETHODIMP Csmapi::get_Recipients(IRecipients **ppVal)
{
HRESULT hr = S_FALSE;
CComObject<Recipients> *pRet = NULL;
if (hr = CComObject<Recipients>::CreateInstance(&pRet))
goto done;
pRet->AddRef();
if (hr = pRet->Init(m_pRecipHead))
goto done;
hr = pRet->QueryInterface(IID_IRecipients, (LPVOID*)ppVal);
done:
if (pRet)
pRet->Release();
return hr;
}
/******************************************
Func:
get_Subject
Abstract:
Return the Subject line information.
Params:
*pVal: returned string
*******************************************/
STDMETHODIMP Csmapi::get_Subject(BSTR *pVal)
{
//GET_BSTR(pVal, m_bstrSubject);
*pVal = m_bstrSubject.Copy();
return S_OK;
}
/******************************************
Func:
put_Subject
Abstract:
Set the Subject line information.
Params:
newVal: new string
*******************************************/
STDMETHODIMP Csmapi::put_Subject(BSTR newVal)
{
m_bstrSubject = newVal;
return S_OK;
}
/******************************************
Func:
get_Body
Abstract:
Get the Body message
Params:
*pVal: body message string
*******************************************/
STDMETHODIMP Csmapi::get_Body(BSTR *pVal)
{
//GET_BSTR(pVal, m_bstrBody);
*pVal = m_bstrBody.Copy();
return S_OK;
}
/******************************************
Func:
put_Body
Abstract:
Set the Body message
Params:
newVal: new body message string
*******************************************/
STDMETHODIMP Csmapi::put_Body(BSTR newVal)
{
m_bstrBody = newVal;
return S_OK;
}
/******************************************
Func:
get_AttachedXMLFile
Abstract:
get Attachment file info.
Params:
*pVal: attachment file pathname.
*******************************************/
STDMETHODIMP Csmapi::get_AttachedXMLFile(BSTR *pVal)
{
//GET_BSTR(pVal, m_bstrXMLFile);
*pVal = m_bstrXMLFile.Copy();
return S_OK;
}
/******************************************
Func:
put_AttachedXMLFile
Abstract:
set Attachment file info.
Params:
newVal: attachment file pathname.
*******************************************/
STDMETHODIMP Csmapi::put_AttachedXMLFile(BSTR newVal)
{
m_bstrXMLFile = newVal;
return S_OK;
}
/* ----------------------------------------------------------- */
/* Internal Helper functions */
/* ----------------------------------------------------------- */
/******************************************
Func:
GetRecipCount
Abstract:
Return the number of recipients
Params:
*******************************************/
ULONG Csmapi::GetRecipCount()
{
ULONG count = 0;
Recipient* p = m_pRecipHead;
while (p)
{
count ++;
p = p->m_pNext;
}
return count;
}
/******************************************
Func:
BuildMapiRecipDesc
Abstract:
Used Simple MAPI MAPIResolveName to resolve the recipient's email alias.
It would pop up an selection box when a conflict was found.
Params:
**ppMapiRecipDesc: Return the resolved MAPI recipients array.
*******************************************/
ULONG Csmapi::BuildMapiRecipDesc(MapiRecipDesc** ppMapiRecipDesc)
{
USES_CONVERSION;
if (!m_bLogonOK)
return 0;
ULONG count = GetRecipCount();
if (count <= 0)
{
PopulateAndThrowErrorInfo(MAPI_E_INVALID_RECIPS);
return 0;
}
*ppMapiRecipDesc = new MapiRecipDesc[count];
if (*ppMapiRecipDesc == NULL)
{
PopulateAndThrowErrorInfo(MAPI_E_INSUFFICIENT_MEMORY);
return 0;
}
ZeroMemory(*ppMapiRecipDesc, sizeof(MapiRecipDesc) * count);
ULONG err = MAPI_E_FAILURE;
Recipient* p = m_pRecipHead;
count = 0;
LPMAPIRESOLVENAME lpfnResolveName = (LPMAPIRESOLVENAME)GetProcAddress(m_hLib, "MAPIResolveName");
if (lpfnResolveName == NULL)
{
PopulateAndThrowErrorInfo(E_FUNC_NOTFOUND);
return -1; // -1 means ResolveName failed.
}
while (p)
{
if (p->m_pRecip)
MAPIFreeBuffer(p->m_pRecip);
err = lpfnResolveName(
m_lhSession,
0,
W2A(p->m_bstrName),
MAPI_DIALOG,
0,
&p->m_pRecip);
if (err != SUCCESS_SUCCESS )
{
count = -1;
break;
}
p->m_pRecip->ulRecipClass = MAPI_TO;
(*ppMapiRecipDesc)[count] = *(p->m_pRecip);
count++;
p = p->m_pNext;
}
// ResolveName failed.
if (err != SUCCESS_SUCCESS)
{
delete *ppMapiRecipDesc;
*ppMapiRecipDesc = NULL;
PopulateAndThrowErrorInfo(err);
}
return count;
}
/******************************************
Func:
MAPIFreeBuffer
Abstract:
MAPIFreeBuffer wrapper.
Params:
*p: buffer pointer will be deleted.
*******************************************/
void Csmapi::MAPIFreeBuffer( MapiRecipDesc* p )
{
if (m_lpfnMapiFreeBuf == NULL && m_hLib)
{
m_lpfnMapiFreeBuf = (LPMAPIFREEBUFFER)GetProcAddress(m_hLib, "MAPIFreeBuffer");
}
if (!m_lpfnMapiFreeBuf)
return;
m_lpfnMapiFreeBuf(p);
}
/******************************************
Func:
AddRecipientInternal
Abstract:
Add one recipient to recipients list.
Params:
*pName: new recipient name.
*******************************************/
HRESULT Csmapi::AddRecipientInternal(char* pName)
{
MACRO_AddRecipientInternal(pName);
}
HRESULT Csmapi::AddRecipientInternal(WCHAR* pName)
{
MACRO_AddRecipientInternal(pName);
}
/******************************************
Func:
GetMAPIDefaultProfile
Abstract:
get default profile string from Registry
Params:
*pProfile: profile string buffer.
*pdwCount: # of char of profile string
*******************************************/
BOOL GetMAPIDefaultProfile(TCHAR* pProfile, DWORD* pdwCount)
{
CRegKey cKey;
LONG lRet;
BOOL bRet = FALSE;
lRet = cKey.Open(HKEY_CURRENT_USER, TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows Messaging Subsystem\\Profiles"), KEY_READ);
if (lRet == ERROR_SUCCESS)
{
lRet = cKey.QueryValue(pProfile, TEXT("DefaultProfile"), pdwCount);
if (lRet == ERROR_SUCCESS)
{
bRet = TRUE;
}
cKey.Close();
}
return bRet;
}
void Csmapi::PopulateAndThrowErrorInfo(ULONG err)
{
UINT uID = 0;
switch (err)
{
case E_FUNC_NOTFOUND:
uID = IDS_E_FUNC_NOTFOUND;
break;
case MAPI_E_FAILURE :
uID = IDS_MAPI_E_FAILURE;
break;
case MAPI_E_INSUFFICIENT_MEMORY :
uID = IDS_MAPI_E_INSUFFICIENT_MEMORY;
break;
case MAPI_E_LOGIN_FAILURE :
uID = IDS_MAPI_E_LOGIN_FAILURE;
break;
case MAPI_E_TOO_MANY_SESSIONS :
uID = IDS_MAPI_E_TOO_MANY_SESSIONS;
break;
case MAPI_E_USER_ABORT :
uID = IDS_MAPI_E_USER_ABORT;
break;
case MAPI_E_INVALID_SESSION :
uID = IDS_MAPI_E_INVALID_SESSION;
break;
case MAPI_E_INVALID_EDITFIELDS :
uID = IDS_MAPI_E_INVALID_EDITFIELDS;
break;
case MAPI_E_INVALID_RECIPS :
uID = IDS_MAPI_E_INVALID_RECIPS;
break;
case MAPI_E_NOT_SUPPORTED :
uID = IDS_MAPI_E_NOT_SUPPORTED;
break;
case MAPI_E_AMBIGUOUS_RECIPIENT :
uID = IDS_MAPI_E_AMBIGUOUS_RECIPIENT;
break;
case MAPI_E_ATTACHMENT_NOT_FOUND :
uID = IDS_MAPI_E_ATTACHMENT_NOT_FOUND;
break;
case MAPI_E_ATTACHMENT_OPEN_FAILURE :
uID = IDS_MAPI_E_ATTACHMENT_OPEN_FAILURE;
break;
case MAPI_E_BAD_RECIPTYPE :
uID = IDS_MAPI_E_BAD_RECIPTYPE;
break;
case MAPI_E_TEXT_TOO_LARGE :
uID = IDS_MAPI_E_TEXT_TOO_LARGE;
break;
case MAPI_E_TOO_MANY_FILES :
uID = IDS_MAPI_E_TOO_MANY_FILES;
break;
case MAPI_E_TOO_MANY_RECIPIENTS :
uID = IDS_MAPI_E_TOO_MANY_RECIPIENTS;
break;
case MAPI_E_UNKNOWN_RECIPIENT :
uID = IDS_MAPI_E_UNKNOWN_RECIPIENT;
break;
default:
uID = IDS_MAPI_E_FAILURE;
}
//Currently the hresult in the Error info structure is set to E_FAIL
Error(uID,IID_Ismapi,E_FAIL,_Module.GetResourceInstance());
}