1052 lines
27 KiB
C++
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
|
|
¬e, // 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());
|
|
}
|