2456 lines
71 KiB
C++
2456 lines
71 KiB
C++
///////////////////////////////////////////////////////////////////////////////
|
|
/* File: mapisend.cpp
|
|
|
|
Description: Implements the most basic MAPI email client to send a message
|
|
to one or more recipients. All operations are done without UI.
|
|
|
|
classes: CMapiSession
|
|
CMapiRecipients
|
|
CMapiMessage
|
|
CMapiMessageBody
|
|
MAPI
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
06/18/97 Initial creation. BrianAu
|
|
06/22/97 Added class MAPI. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
#include "precomp.hxx"
|
|
#pragma hdrstop
|
|
|
|
#include "mapisend.h"
|
|
|
|
|
|
//
|
|
// Global MAPI object to provide dynamic linking to MAPI32.DLL.
|
|
// All MAPI32.DLL functions are called through this object.
|
|
//
|
|
MAPI MAPI32;
|
|
|
|
|
|
//
|
|
// How many entries we grow the recipients list by when it is enlarged.
|
|
//
|
|
#ifdef DEBUG
|
|
//
|
|
// For debugging and development, stress the list-growth code by making
|
|
// it extend the list each time a recipient is added.
|
|
//
|
|
UINT CMapiRecipients::m_cGrowIncr = 1;
|
|
#else // !DEBUG
|
|
//
|
|
// For production builds, fix the growth increment at 3. 3 is arbitrary
|
|
// but is probably a good conservative guess. Want to avoid
|
|
// list growth in the typical scenario.
|
|
//
|
|
// 1 for the quota user.
|
|
// 1 for the volume administrator.
|
|
// 1 for the user's manager (? probably not)
|
|
//
|
|
// Note that the list growth code always runs at least once because
|
|
// we use it to create the initial list.
|
|
//
|
|
UINT CMapiRecipients::m_cGrowIncr = 3;
|
|
#endif // DEBUG
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: CMapiRecipients::CMapiRecipients
|
|
|
|
Description: Constructor.
|
|
|
|
Arguments: None.
|
|
|
|
Returns: Nothing.
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
06/18/97 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
CMapiRecipients::CMapiRecipients(
|
|
BOOL bUnicode
|
|
) : m_pal(NULL),
|
|
m_bUnicode(bUnicode),
|
|
m_cMaxEntries(0)
|
|
{
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: CMapiRecipients::~CMapiRecipients
|
|
|
|
Description: Destructor.
|
|
Frees the MAPI address list.
|
|
|
|
Arguments: None.
|
|
|
|
Returns: Nothing.
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
06/18/97 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
CMapiRecipients::~CMapiRecipients(
|
|
VOID
|
|
)
|
|
{
|
|
if (NULL != m_pal)
|
|
{
|
|
MAPI32.FreePadrlist(m_pal);
|
|
}
|
|
}
|
|
|
|
CMapiRecipients::CMapiRecipients(
|
|
const CMapiRecipients& rhs
|
|
) : m_pal(NULL),
|
|
m_bUnicode(FALSE),
|
|
m_cMaxEntries(0)
|
|
{
|
|
#ifdef UNICODE
|
|
m_bUnicode = TRUE;
|
|
#endif
|
|
|
|
*this = rhs;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: CMapiRecipients::operator = (const CMapiRecipients& rhs)
|
|
|
|
Description: Assignment copy.
|
|
|
|
Arguments:
|
|
rhs - Reference to source recipient list.
|
|
|
|
Returns: Reference to destination recipient list.
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
06/18/97 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
CMapiRecipients&
|
|
CMapiRecipients::operator = (
|
|
const CMapiRecipients& rhs
|
|
)
|
|
{
|
|
if (this != &rhs)
|
|
{
|
|
BOOL bConvertStrings = m_bUnicode != rhs.m_bUnicode;
|
|
|
|
//
|
|
// Delete the current address list.
|
|
//
|
|
if (NULL != m_pal)
|
|
{
|
|
MAPI32.FreePadrlist(m_pal);
|
|
m_pal = NULL;
|
|
}
|
|
|
|
//
|
|
// Copy the Max entry count.
|
|
//
|
|
// NOTE: We DO NOT copy the m_bUnicode attribute.
|
|
// This attribute stays with the object for life.
|
|
//
|
|
m_cMaxEntries = rhs.m_cMaxEntries;
|
|
|
|
if (NULL != rhs.m_pal)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
UINT cb;
|
|
|
|
cb = sizeof(ADRLIST) + ((m_cMaxEntries - 1) * sizeof(ADRENTRY));
|
|
hr = MAPI32.AllocateBuffer(cb, (LPVOID *)&m_pal);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
ZeroMemory(m_pal, cb); // Note: m_pal->cEntries is init'd to 0.
|
|
if (NULL != m_pal)
|
|
{
|
|
for (UINT i = 0; i < rhs.m_pal->cEntries && SUCCEEDED(hr); i++)
|
|
{
|
|
hr = CopyAdrListEntry(m_pal->aEntries[i],
|
|
rhs.m_pal->aEntries[i],
|
|
bConvertStrings);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
m_pal->cEntries++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (FAILED(hr))
|
|
{
|
|
//
|
|
// Something went wrong. Leave the object in an empty state.
|
|
//
|
|
if (NULL != m_pal)
|
|
MAPI32.FreePadrlist(m_pal);
|
|
|
|
m_pal = NULL;
|
|
m_cMaxEntries = 0;
|
|
}
|
|
}
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: CMapiRecipients::Count
|
|
|
|
Description: Returns the count of valid entries in the address list.
|
|
|
|
Arguments: None.
|
|
|
|
Returns: Count of entries.
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
06/18/97 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
INT
|
|
CMapiRecipients::Count(
|
|
VOID
|
|
) const
|
|
{
|
|
return m_pal ? m_pal->cEntries : 0;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: CMapiRecipients::AddRecipient
|
|
|
|
Description: Adds a new recipient/recipient-type pair to the address list.
|
|
|
|
Arguments:
|
|
pszEmailName - Name of recipient typically used as an email destination.
|
|
|
|
dwType - Recipient type. Can be one of the following:
|
|
|
|
MAPI_ORIG
|
|
MAPI_TO
|
|
MAPI_CC
|
|
MAPI_BCC
|
|
|
|
Returns:
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
06/18/97 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CMapiRecipients::AddRecipient(
|
|
LPCTSTR pszEmailName,
|
|
DWORD dwType
|
|
)
|
|
{
|
|
HRESULT hr = NO_ERROR;
|
|
|
|
if (NULL == m_pal || m_pal->cEntries == m_cMaxEntries)
|
|
{
|
|
//
|
|
// Either we're just starting up (no list created yet),
|
|
// or the current list is full. Grow the list.
|
|
//
|
|
hr = Grow(m_cGrowIncr);
|
|
}
|
|
if (SUCCEEDED(hr) && NULL != m_pal)
|
|
{
|
|
UINT cb;
|
|
INT i = m_pal->cEntries++;
|
|
|
|
m_pal->aEntries[i].ulReserved1 = 0;
|
|
m_pal->aEntries[i].cValues = 2;
|
|
|
|
//
|
|
// Allocate the SPropValue buffer for this new entry.
|
|
// Our entries have 2 values (name and type).
|
|
// Caller must call IAddrBook::ResolveName() to get the remaining
|
|
// recipient information.
|
|
//
|
|
cb = sizeof(SPropValue) * m_pal->aEntries[i].cValues;
|
|
hr = MAPI32.AllocateBuffer(cb, (LPVOID *)&m_pal->aEntries[i].rgPropVals);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
ZeroMemory(m_pal->aEntries[i].rgPropVals, cb);
|
|
//
|
|
// Allocate the buffer for the recipient email name string.
|
|
//
|
|
hr = MAPI32.AllocateMore((lstrlen(pszEmailName)+1) * sizeof(TCHAR),
|
|
(LPVOID)m_pal->aEntries[i].rgPropVals,
|
|
(LPVOID *)&m_pal->aEntries[i].rgPropVals[0].Value.LPSZ);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// Store the recipient email name string.
|
|
//
|
|
m_pal->aEntries[i].rgPropVals[0].ulPropTag = PR_DISPLAY_NAME;
|
|
lstrcpy(m_pal->aEntries[i].rgPropVals[0].Value.LPSZ, pszEmailName);
|
|
|
|
//
|
|
// Store the recipient type (i.e. MAPI_TO, MAPI_CC etc).
|
|
//
|
|
m_pal->aEntries[i].rgPropVals[1].ulPropTag = PR_RECIPIENT_TYPE;
|
|
m_pal->aEntries[i].rgPropVals[1].Value.l = dwType;
|
|
}
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: CMapiRecipients::Grow
|
|
|
|
Description: Increases the size of the address list, preserving any
|
|
existing list entries.
|
|
|
|
Arguments:
|
|
cGrowIncr - Number of entries to grow the list by.
|
|
|
|
Returns:
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
06/18/97 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CMapiRecipients::Grow(
|
|
UINT cGrowIncr
|
|
)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
LPADRLIST m_palNew = NULL;
|
|
UINT cb;
|
|
|
|
//
|
|
// Allocate the new buffer m_cGrowIncr entries larger than the
|
|
// current buffer. The (-1) is because the declaration of ADRLIST already
|
|
// includes one entry.
|
|
//
|
|
cb = sizeof(ADRLIST) + ((m_cMaxEntries + cGrowIncr - 1) * sizeof(ADRENTRY));
|
|
hr = MAPI32.AllocateBuffer(cb, (LPVOID *)&m_palNew);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
ZeroMemory(m_palNew, cb); // Note: m_palNew->cEntries is init'd to 0.
|
|
if (NULL != m_pal)
|
|
{
|
|
//
|
|
// We have an existing address list.
|
|
// Copy it to the new list buffer.
|
|
// If we fail the copy of an entry, we abort the loop and m_palNew->cEntries
|
|
// accurately reflects how many valid entries we have.
|
|
//
|
|
for (UINT i = 0; i < m_pal->cEntries && SUCCEEDED(hr); i++)
|
|
{
|
|
hr = CopyAdrListEntry(m_palNew->aEntries[i], m_pal->aEntries[i], FALSE);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
m_palNew->cEntries++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// Delete the original list (if it exists) and store the
|
|
// address of the new list in m_pal.
|
|
//
|
|
LPADRLIST palOrig = m_pal;
|
|
m_pal = m_palNew;
|
|
if (NULL != palOrig)
|
|
MAPI32.FreePadrlist(palOrig);
|
|
|
|
m_cMaxEntries += cGrowIncr;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Something went wrong. Just delete the new list and keep the old one
|
|
// the way it was.
|
|
//
|
|
if (NULL != m_palNew)
|
|
MAPI32.FreePadrlist(m_palNew);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: CMapiRecipients::CopyAdrListEntry
|
|
|
|
Description: Copies a single list entry from one entry structure to another.
|
|
All entry-type-specific issues are addressed.
|
|
|
|
Arguments:
|
|
Dest - Reference to destination entry structure.
|
|
|
|
Src - Reference to source entry structure.
|
|
|
|
Returns:
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
06/18/97 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CMapiRecipients::CopyAdrListEntry(
|
|
ADRENTRY& Dest,
|
|
ADRENTRY& Src,
|
|
BOOL bConvertStrings
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
UINT cb = 0;
|
|
|
|
//
|
|
// Allocate buffer for the new entry and it's property values.
|
|
//
|
|
cb = sizeof(SPropValue) * Src.cValues;
|
|
hr = MAPI32.AllocateBuffer(cb, (LPVOID *)&Dest.rgPropVals);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
ZeroMemory(Dest.rgPropVals, cb);
|
|
Dest.cValues = 0;
|
|
//
|
|
// Copy each of the values.
|
|
// If we fail the copy of a value, we abort the loop and Dest.cValues
|
|
// accurately reflects how many valid prop values we have.
|
|
//
|
|
for (UINT i = 0; i < Src.cValues && SUCCEEDED(hr); i++)
|
|
{
|
|
hr = CopySPropVal((LPVOID)Dest.rgPropVals, // Base for new allocations
|
|
Dest.rgPropVals[i], // Destination SPropVal
|
|
Src.rgPropVals[i], // Source SPropVal
|
|
bConvertStrings);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
Dest.cValues++;
|
|
}
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: CMapiRecipients::CopySPropVal
|
|
|
|
Description: Copies a single property value from one SPropValue object
|
|
to another. Used by CopyAdrListEntry to copy the individual properties
|
|
belonging to an entry.
|
|
|
|
Arguments:
|
|
pvBaseAlloc - Pointer to use as the "lpObject" argument in a call
|
|
to MAPIAllocateMore() if memory must be reallocated during
|
|
the copy process.
|
|
|
|
Dest - Reference to destination property value structure.
|
|
|
|
Src - Reference to source property value structure.
|
|
|
|
Returns:
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
06/18/97 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CMapiRecipients::CopySPropVal(
|
|
LPVOID pvBaseAlloc,
|
|
SPropValue& Dest,
|
|
SPropValue& Src,
|
|
BOOL bConvertStrings
|
|
)
|
|
{
|
|
HRESULT hr = NO_ERROR;
|
|
BOOL bCopyTag = TRUE;
|
|
|
|
//
|
|
// Copy method varies depending on property type.
|
|
//
|
|
switch(PROP_TYPE(Src.ulPropTag))
|
|
{
|
|
case PT_I2:
|
|
Dest.Value.i = Src.Value.i;
|
|
break;
|
|
case PT_LONG:
|
|
Dest.Value.l = Src.Value.l;
|
|
break;
|
|
case PT_R4:
|
|
Dest.Value.flt = Src.Value.flt;
|
|
break;
|
|
case PT_DOUBLE:
|
|
Dest.Value.dbl = Src.Value.dbl;
|
|
break;
|
|
case PT_BOOLEAN:
|
|
Dest.Value.b = Src.Value.b;
|
|
break;
|
|
case PT_CURRENCY:
|
|
Dest.Value.cur = Src.Value.cur;
|
|
break;
|
|
case PT_APPTIME:
|
|
Dest.Value.at = Src.Value.at;
|
|
break;
|
|
case PT_SYSTIME:
|
|
Dest.Value.ft = Src.Value.ft;
|
|
break;
|
|
case PT_I8:
|
|
Dest.Value.li = Src.Value.li;
|
|
break;
|
|
case PT_ERROR:
|
|
Dest.Value.err = Src.Value.err;
|
|
break;
|
|
case PT_NULL:
|
|
case PT_OBJECT:
|
|
Dest.Value.x = Src.Value.x;
|
|
break;
|
|
case PT_STRING8:
|
|
if (bConvertStrings && m_bUnicode)
|
|
{
|
|
//
|
|
// The recipients list is unicode, the source is ANSI
|
|
// and we're supposed to convert strings. That means
|
|
// we need to convert from Ansi to Unicode.
|
|
//
|
|
hr = CopySPropValString(pvBaseAlloc,
|
|
&Dest.Value.lpszW,
|
|
Src.Value.lpszA);
|
|
|
|
Dest.ulPropTag = PROP_TAG(PT_UNICODE, PROP_ID(Src.ulPropTag));
|
|
bCopyTag = FALSE;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// No conversion required. Just a straight copy.
|
|
//
|
|
hr = CopyVarLengthSPropVal(pvBaseAlloc,
|
|
(LPVOID *)&Dest.Value.lpszA,
|
|
Src.Value.lpszA,
|
|
(lstrlenA(Src.Value.lpszA)+1) * sizeof(char));
|
|
}
|
|
break;
|
|
|
|
case PT_UNICODE:
|
|
if (bConvertStrings && !m_bUnicode)
|
|
{
|
|
//
|
|
// The recipients list is Ansi, the source is Unicode
|
|
// and we're supposed to convert strings. That means
|
|
// we need to convert from Unicode to Ansi.
|
|
//
|
|
hr = CopySPropValString(pvBaseAlloc,
|
|
&Dest.Value.lpszA,
|
|
Src.Value.lpszW);
|
|
|
|
Dest.ulPropTag = PROP_TAG(PT_STRING8, PROP_ID(Src.ulPropTag));
|
|
bCopyTag = FALSE;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// No conversion required. Just a straight copy.
|
|
//
|
|
hr = CopyVarLengthSPropVal(pvBaseAlloc,
|
|
(LPVOID *)&Dest.Value.lpszW,
|
|
Src.Value.lpszW,
|
|
(lstrlenW(Src.Value.lpszW)+1) * sizeof(WCHAR));
|
|
}
|
|
break;
|
|
|
|
case PT_BINARY:
|
|
hr = CopyVarLengthSPropVal(pvBaseAlloc,
|
|
(LPVOID *)&Dest.Value.bin.lpb,
|
|
Src.Value.bin.lpb,
|
|
Src.Value.bin.cb);
|
|
break;
|
|
case PT_CLSID:
|
|
hr = CopyVarLengthSPropVal(pvBaseAlloc,
|
|
(LPVOID *)&Dest.Value.lpguid,
|
|
Src.Value.lpguid,
|
|
sizeof(*(Src.Value.lpguid)));
|
|
break;
|
|
default:
|
|
//
|
|
// FEATURE: Assert here so we know if we should be handling
|
|
// some other property type.
|
|
//
|
|
hr = E_FAIL;
|
|
break;
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// Copy the common stuff.
|
|
//
|
|
Dest.dwAlignPad = Src.dwAlignPad;
|
|
if (bCopyTag)
|
|
{
|
|
Dest.ulPropTag = Src.ulPropTag;
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: CMapiRecipients::CopyVarLengthSPropVal
|
|
|
|
Description: Copies a single variable-length property value item from
|
|
one location in memory to another. Memory for the destination is
|
|
automatically allocated. This function is used to copy prop values
|
|
of types STRING, BINARY etc.
|
|
|
|
Arguments:
|
|
pvBaseAlloc - Pointer to use as the "lpObject" argument in a call
|
|
to MAPIAllocateMore().
|
|
|
|
ppvDest - Address of pointer variable to receive the address of
|
|
the newly allocated buffer.
|
|
|
|
pvSrc - Address of source buffer.
|
|
|
|
cb - Number of bytes to copy from pvSrc to *ppvDest.
|
|
|
|
Returns:
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
06/18/97 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CMapiRecipients::CopyVarLengthSPropVal(
|
|
LPVOID pvBaseAlloc,
|
|
LPVOID *ppvDest,
|
|
LPVOID pvSrc,
|
|
INT cb
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = MAPI32.AllocateMore(cb, pvBaseAlloc, ppvDest);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
CopyMemory(*ppvDest, pvSrc, cb);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: CMapiRecipients::CopySPropValString (ANSI -> UNICODE)
|
|
|
|
Description: Copies a string property value item from one location
|
|
to another; performing ANSI/UNICODE translations as required.
|
|
|
|
Arguments:
|
|
pvBaseAlloc - Pointer to use as the "lpObject" argument in a call
|
|
to MAPIAllocateMore().
|
|
|
|
ppszDestW - Address of pointer variable to receive the address of
|
|
the newly wide character buffer.
|
|
|
|
pszSrcA - Address of ANSI source buffer.
|
|
|
|
Returns:
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
06/18/97 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CMapiRecipients::CopySPropValString(
|
|
LPVOID pvBaseAlloc,
|
|
LPWSTR *ppszDestW,
|
|
LPCSTR pszSrcA
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
|
|
INT cchW = MultiByteToWideChar(CP_ACP,
|
|
0,
|
|
pszSrcA,
|
|
-1,
|
|
NULL,
|
|
0);
|
|
|
|
hr = MAPI32.AllocateMore(cchW * sizeof(WCHAR), pvBaseAlloc, (LPVOID *)ppszDestW);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
MultiByteToWideChar(CP_ACP,
|
|
0,
|
|
pszSrcA,
|
|
-1,
|
|
*ppszDestW,
|
|
cchW);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: CMapiRecipients::CopySPropValString (UNICODE -> ANSI)
|
|
|
|
Description: Copies a string property value item from one location
|
|
to another; performing ANSI/UNICODE translations as required.
|
|
|
|
Arguments:
|
|
pvBaseAlloc - Pointer to use as the "lpObject" argument in a call
|
|
to MAPIAllocateMore().
|
|
|
|
ppszDestA - Address of pointer variable to receive the address of
|
|
the newly ANSI character buffer.
|
|
|
|
pszSrcW - Address of UNICODE source buffer.
|
|
|
|
Returns:
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
06/18/97 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CMapiRecipients::CopySPropValString(
|
|
LPVOID pvBaseAlloc,
|
|
LPSTR *ppszDestA,
|
|
LPCWSTR pszSrcW
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
|
|
INT cchA = WideCharToMultiByte(CP_ACP,
|
|
0,
|
|
pszSrcW,
|
|
-1,
|
|
NULL,
|
|
0,
|
|
NULL, NULL);
|
|
|
|
hr = MAPI32.AllocateMore(cchA * sizeof(CHAR), pvBaseAlloc, (LPVOID *)ppszDestA);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
WideCharToMultiByte(CP_ACP,
|
|
0,
|
|
pszSrcW,
|
|
-1,
|
|
*ppszDestA,
|
|
cchA,
|
|
NULL, NULL);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: CMapiSession::CMapiSession
|
|
|
|
Description: Constructor.
|
|
|
|
Arguments: None.
|
|
|
|
Returns:
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
06/18/97 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
CMapiSession::CMapiSession(
|
|
VOID
|
|
) : m_pSession(NULL),
|
|
m_pDefMsgStore(NULL),
|
|
m_pOutBoxFolder(NULL),
|
|
m_bMapiInitialized(FALSE)
|
|
{
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: CMapiSession::CMapiSession
|
|
|
|
Description: Constructor. Initializes MAPI.
|
|
|
|
Arguments: None.
|
|
|
|
Returns:
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
06/18/97 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
CMapiSession::~CMapiSession(
|
|
VOID
|
|
)
|
|
{
|
|
if (NULL != m_pOutBoxFolder)
|
|
{
|
|
m_pOutBoxFolder->Release();
|
|
}
|
|
if (NULL != m_pDefMsgStore)
|
|
{
|
|
m_pDefMsgStore->Release();
|
|
}
|
|
if (NULL != m_pSession)
|
|
{
|
|
m_pSession->Release();
|
|
}
|
|
if (m_bMapiInitialized)
|
|
{
|
|
//
|
|
// If MAPI was initialized, uninitialize it.
|
|
//
|
|
MAPI32.Uninitialize();
|
|
//
|
|
// Unload MAPI32.DLL.
|
|
//
|
|
MAPI32.Unload();
|
|
}
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: CMapiSession::Initialize
|
|
|
|
Description: Initializes the session object by:
|
|
|
|
1. Initializing MAPI if neccessary,
|
|
2. Logging on to create the MAPI session object.
|
|
3. Open the default msg store.
|
|
4. Open the outbox folder in the default msg store.
|
|
|
|
Arguments: None.
|
|
|
|
Returns:
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
06/18/97 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CMapiSession::Initialize(
|
|
VOID
|
|
)
|
|
{
|
|
HRESULT hr = NO_ERROR;
|
|
|
|
if (!m_bMapiInitialized)
|
|
{
|
|
//
|
|
// Load MAPI32.DLL.
|
|
//
|
|
MAPI32.Load();
|
|
|
|
//
|
|
// Initialize MAPI if it hasn't been initialized.
|
|
//
|
|
hr = MAPI32.Initialize(NULL);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// Remember that MAPI has been initialized.
|
|
//
|
|
m_bMapiInitialized = TRUE;
|
|
}
|
|
}
|
|
if (m_bMapiInitialized)
|
|
{
|
|
//
|
|
// Attempt logon only if MAPI has been initialized.
|
|
//
|
|
DWORD dwLogonFlags = MAPI_TIMEOUT_SHORT | MAPI_USE_DEFAULT | MAPI_EXTENDED | MAPI_ALLOW_OTHERS;
|
|
#ifdef UNICODE
|
|
dwLogonFlags |= MAPI_UNICODE;
|
|
#endif
|
|
if (NULL != m_pSession)
|
|
{
|
|
//
|
|
// Release any previously-held session interface ptr.
|
|
//
|
|
m_pSession->Release();
|
|
m_pSession = NULL;
|
|
}
|
|
hr = MAPI32.LogonEx(0, // Hwnd for any UI.
|
|
NULL, // Profile name.
|
|
NULL, // Password.
|
|
dwLogonFlags, // Flags
|
|
&m_pSession); // Session obj ptr (out).
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
ReportErrorsReturned(hr);
|
|
//
|
|
// We're logged on. Open the default msg store and out box folder.
|
|
//
|
|
hr = OpenDefMsgStore();
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = OpenOutBoxFolder();
|
|
}
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: CMapiSession::OpenDefMsgStore
|
|
|
|
Description: Opens the session's default message store.
|
|
Stores the resulting IMsgStore ptr in m_pDefMsgStore.
|
|
|
|
Arguments: None.
|
|
|
|
Returns:
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
06/18/97 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CMapiSession::OpenDefMsgStore(
|
|
VOID
|
|
)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
SPropValue spv;
|
|
|
|
SizedSPropTagArray(2, sptCols) = {2, PR_ENTRYID, PR_DEFAULT_STORE};
|
|
SRestriction sres;
|
|
|
|
if (NULL != m_pSession)
|
|
{
|
|
LPMAPITABLE pTable;
|
|
hr = m_pSession->GetMsgStoresTable(0, &pTable);
|
|
ReportErrorsReturned(hr);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// Find the entry ID for the default store in the session's
|
|
// msg stores table.
|
|
//
|
|
LPSRowSet pRow = NULL;
|
|
|
|
sres.rt = RES_PROPERTY;
|
|
sres.res.resProperty.relop = RELOP_EQ;
|
|
sres.res.resProperty.ulPropTag = PR_DEFAULT_STORE;
|
|
sres.res.resProperty.lpProp = &spv;
|
|
|
|
spv.ulPropTag = PR_DEFAULT_STORE;
|
|
spv.Value.b = TRUE;
|
|
|
|
hr = MAPI32.HrQueryAllRows(pTable, // Table ptr.
|
|
(LPSPropTagArray)&sptCols, // Column set
|
|
&sres, // Row restrictions
|
|
NULL, // Sort order set
|
|
0, // All rows.
|
|
&pRow); // Resulting row set (out)
|
|
|
|
ReportErrorsReturned(hr);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
SBinary sbEID = {0, NULL};
|
|
|
|
if (NULL != pRow &&
|
|
0 != pRow->cRows &&
|
|
0 != pRow->aRow[0].cValues &&
|
|
PR_ENTRYID == pRow->aRow[0].lpProps[0].ulPropTag)
|
|
{
|
|
sbEID = pRow->aRow[0].lpProps[0].Value.bin;
|
|
|
|
//
|
|
// Found the ID. Now open the store.
|
|
//
|
|
if (NULL != m_pDefMsgStore)
|
|
{
|
|
//
|
|
// Release any previously-held store interface ptr.
|
|
//
|
|
m_pDefMsgStore->Release();
|
|
m_pDefMsgStore = NULL;
|
|
}
|
|
hr = m_pSession->OpenMsgStore(0, // Hwnd for any UI
|
|
sbEID.cb, // Entry ID size.
|
|
(LPENTRYID)sbEID.lpb, // Entry ID ptr.
|
|
NULL, // Use Std iface.
|
|
MAPI_BEST_ACCESS, // read/write access
|
|
&m_pDefMsgStore); // Store ptr (out)
|
|
|
|
ReportErrorsReturned(hr);
|
|
}
|
|
else
|
|
{
|
|
hr = MAPI_E_NOT_FOUND;
|
|
}
|
|
MAPI32.FreeProws(pRow);
|
|
}
|
|
pTable->Release();
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: CMapiSession::GetSessionUser
|
|
|
|
Description: Returns the address properties for the session user.
|
|
|
|
Arguments: None.
|
|
|
|
Returns:
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
06/18/97 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CMapiSession::GetSessionUser(
|
|
LPSPropValue *ppProps,
|
|
ULONG *pcbProps
|
|
)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
if (NULL != m_pSession)
|
|
{
|
|
ULONG cbEID = 0;
|
|
LPENTRYID lpEID = NULL;
|
|
//
|
|
// Get the "identity" of the session.
|
|
// In general, this is the user's entry ID.
|
|
//
|
|
hr = m_pSession->QueryIdentity(&cbEID, &lpEID);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
LPADRBOOK pAddrBook = NULL;
|
|
hr = GetAddressBook(&pAddrBook);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
ULONG ulObjType = 0;
|
|
IMAPIProp *pMailUser = NULL;
|
|
|
|
//
|
|
// Open the user's entry in the address book.
|
|
//
|
|
hr = pAddrBook->OpenEntry(cbEID,
|
|
lpEID,
|
|
NULL,
|
|
0,
|
|
&ulObjType,
|
|
(LPUNKNOWN *)&pMailUser);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
ULONG ulFlags = 0;
|
|
ULONG cProps = 0;
|
|
#ifdef UNICODE
|
|
//
|
|
// For unicode builds, we want UNICODE property strings.
|
|
//
|
|
ulFlags |= MAPI_UNICODE;
|
|
#endif
|
|
|
|
SizedSPropTagArray(5, tags) = { 5, PR_ADDRTYPE,
|
|
PR_DISPLAY_NAME,
|
|
PR_EMAIL_ADDRESS,
|
|
PR_ENTRYID,
|
|
PR_SEARCH_KEY };
|
|
|
|
//
|
|
// Retrieve the user properties and return them to
|
|
// the caller.
|
|
//
|
|
hr = pMailUser->GetProps((LPSPropTagArray)&tags, // Prop tags
|
|
ulFlags,
|
|
pcbProps, // Prop cnt (out)
|
|
ppProps); // Prop ptr (out)
|
|
ReportErrorsReturned(hr);
|
|
pMailUser->Release();
|
|
}
|
|
pAddrBook->Release();
|
|
}
|
|
MAPI32.FreeBuffer(lpEID);
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: CMapiSession::OpenOutBoxFolder
|
|
|
|
Description: Opens the outbox folder in the default message store.
|
|
Stores the resulting IMAPIFolder ptr in m_pOutBoxFolder.
|
|
|
|
Arguments: None.
|
|
|
|
Returns:
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
06/18/97 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CMapiSession::OpenOutBoxFolder(
|
|
VOID
|
|
)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
if (NULL != m_pSession && NULL != m_pDefMsgStore)
|
|
{
|
|
LPSPropValue pProps = NULL;
|
|
ULONG ulObjType;
|
|
ULONG cProps;
|
|
ULONG ulFlags = 0;
|
|
#ifdef UNICODE
|
|
//
|
|
// For unicode builds, we want UNICODE property strings.
|
|
//
|
|
ulFlags |= MAPI_UNICODE;
|
|
#endif
|
|
|
|
SizedSPropTagArray(1, sptFolders) = { 1, PR_IPM_OUTBOX_ENTRYID };
|
|
|
|
//
|
|
// Retrieve the entry ID for the outbox in the default msg store.
|
|
//
|
|
hr = m_pDefMsgStore->GetProps((LPSPropTagArray)&sptFolders, // Prop tags
|
|
ulFlags,
|
|
&cProps, // Prop cnt (out)
|
|
&pProps); // Prop ptr (out)
|
|
|
|
ReportErrorsReturned(hr);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (0 != cProps && NULL != pProps)
|
|
{
|
|
if (pProps[0].ulPropTag == sptFolders.aulPropTag[0])
|
|
{
|
|
//
|
|
// Get the MAPI folder interface ptr for the outbox folder.
|
|
//
|
|
if (NULL != m_pOutBoxFolder)
|
|
{
|
|
//
|
|
// Release any previously-held outbox interface ptr.
|
|
//
|
|
m_pOutBoxFolder->Release();
|
|
m_pOutBoxFolder = NULL;
|
|
}
|
|
hr = m_pSession->OpenEntry(pProps[0].Value.bin.cb,
|
|
(LPENTRYID)pProps[0].Value.bin.lpb,
|
|
NULL,
|
|
MAPI_MODIFY,
|
|
&ulObjType,
|
|
(LPUNKNOWN *)&m_pOutBoxFolder);
|
|
|
|
ReportErrorsReturned(hr);
|
|
}
|
|
else
|
|
{
|
|
hr = MAPI_E_NOT_FOUND;
|
|
}
|
|
MAPI32.FreeBuffer(pProps);
|
|
}
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: CMapiSession::Send
|
|
|
|
Description: Sends a message to a list of recipients. There are 3
|
|
versions that allow simple and complex formatting of the
|
|
message body:
|
|
|
|
1. First version lets you pass in simple text strings for the
|
|
subject and body text. This is the simplest way to send a
|
|
short, simple message.
|
|
|
|
2. Second version lets you pass in the subject as a simple text
|
|
string but then lets you create a complex message body as
|
|
a CMapiMessageBody object. This probably won't get used much.
|
|
|
|
3. The third version lets you create a CMapiMessage object
|
|
containing subject line and body text. This is the method
|
|
to use if you want to create a message with complex formatting.
|
|
|
|
Sending a message with CMapiSession::Send ensures that the
|
|
recipient list contains fully resolved names. If you send
|
|
a message with CMapiMessage::Send, you must resolve the names
|
|
before the Send call is made.
|
|
|
|
Arguments:
|
|
pAdrList - Address of MAPI ADRLIST structure containing the
|
|
list of recipient addresses. It is assumed that
|
|
the list contains unresolved recipients but this is not a
|
|
requirement.
|
|
|
|
pszSubject - Address of subject line text.
|
|
|
|
pszBody - Address of msg body text.
|
|
|
|
body - Reference to CMapiMessageBody object containing the message text.
|
|
|
|
msg - Reference to CMapiMessage object containing the subject line
|
|
and message body text.
|
|
|
|
Returns:
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
06/18/97 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Simplest form. Just give an address list, subject line and body
|
|
// text string.
|
|
//
|
|
HRESULT
|
|
CMapiSession::Send(
|
|
LPADRLIST pAdrList,
|
|
LPCTSTR pszSubject,
|
|
LPCTSTR pszBody
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
//
|
|
// Create a local CMapiMessage object with the given subject
|
|
// line and body text. Then just send it.
|
|
//
|
|
CMapiMessage msg(m_pOutBoxFolder);
|
|
hr = msg.SetSubject(pszSubject);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = msg.Append(pszBody);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = Send(pAdrList, msg);
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// If you already have a CMapiMessageBody object created with text, this is the
|
|
// version you want to use.
|
|
//
|
|
HRESULT
|
|
CMapiSession::Send(
|
|
LPADRLIST pAdrList,
|
|
LPCTSTR pszSubject,
|
|
CMapiMessageBody& body
|
|
)
|
|
{
|
|
//
|
|
// Create a local CMapiMessage object with the given subject
|
|
// line and body text. Then just send it.
|
|
//
|
|
CMapiMessage msg(m_pOutBoxFolder, body, pszSubject);
|
|
|
|
return Send(pAdrList, msg);
|
|
}
|
|
|
|
|
|
//
|
|
// If you already have a CMapiMessage object create with subject line
|
|
// and body text, use this. The other versions of Send() eventually
|
|
// call this one.
|
|
//
|
|
HRESULT
|
|
CMapiSession::Send(
|
|
LPADRLIST pAdrList,
|
|
CMapiMessage& msg
|
|
)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
hr = ResolveAddresses(pAdrList);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = msg.Send(pAdrList);
|
|
DebugMsg(DM_ERROR, TEXT("CMapiSession::Send, Result = 0x%08X"), hr);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: CMapiSession::GetAddressBook
|
|
|
|
Description: Returns the session's address book pointer.
|
|
|
|
Arguments:
|
|
ppAdrBook - Address of pointer variable to receive pointer value.
|
|
|
|
Returns:
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
06/18/97 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CMapiSession::GetAddressBook(
|
|
LPADRBOOK *ppAdrBook
|
|
)
|
|
{
|
|
HRESULT hr = E_POINTER;
|
|
if (NULL != m_pSession && NULL != ppAdrBook)
|
|
{
|
|
hr = m_pSession->OpenAddressBook(0, // Hwnd for UI
|
|
NULL, // Use std interface
|
|
AB_NO_DIALOG, // No UI.
|
|
ppAdrBook); // Book ptr (out)
|
|
|
|
ReportErrorsReturned(hr);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: CMapiSession::ReportErrorsReturned [static]
|
|
|
|
Description: When a MAPI function returns MAPI_W_ERRORS_RETURNED,
|
|
error information can be obtained by calling IMapiSession::GetLastError.
|
|
This function encapsulates the necessary behavior to get this error
|
|
information and dump it to the debugger. An option to write a
|
|
warning/error to the system event log is planned.
|
|
|
|
Arguments:
|
|
hr - HRESULT containing the error code.
|
|
|
|
bLogEvent [optional] - If True, write an event to the system event
|
|
log. This option is not in place yet.
|
|
|
|
Returns: Nothing.
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
06/16/97 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
VOID
|
|
CMapiSession::ReportErrorsReturned(
|
|
HRESULT hr,
|
|
BOOL bLogEvent // Unused at this time.
|
|
)
|
|
{
|
|
if (MAPI_W_ERRORS_RETURNED == hr)
|
|
{
|
|
LPMAPIERROR pMapiErrors = NULL;
|
|
DWORD dwFlags = 0;
|
|
#ifdef UNICODE
|
|
dwFlags |= MAPI_UNICODE;
|
|
#endif
|
|
hr = m_pSession->GetLastError(hr, dwFlags, &pMapiErrors);
|
|
if (S_OK == hr)
|
|
{
|
|
if (NULL != pMapiErrors)
|
|
{
|
|
DebugMsg(DM_ERROR, TEXT("MAPI returned errors.\n"));
|
|
DebugMsg(DM_ERROR, TEXT("\tVersion.......: %d"), pMapiErrors->ulVersion);
|
|
DebugMsg(DM_ERROR, TEXT("\tComponent.....: %s"), pMapiErrors->lpszComponent ?
|
|
pMapiErrors->lpszComponent :
|
|
TEXT("Not Provided"));
|
|
DebugMsg(DM_ERROR, TEXT("\tError.........: %s"), pMapiErrors->lpszError ?
|
|
pMapiErrors->lpszError :
|
|
TEXT("Not Provided"));
|
|
DebugMsg(DM_ERROR, TEXT("\tContext.......: %d"), pMapiErrors->ulContext);
|
|
DebugMsg(DM_ERROR, TEXT("\tLowLevel Error: %d\n"), pMapiErrors->ulLowLevelError);
|
|
if (bLogEvent)
|
|
{
|
|
//
|
|
// Open event log and write error?
|
|
//
|
|
}
|
|
MAPI32.FreeBuffer(pMapiErrors);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: CMapiSession::GetOutBoxFolder
|
|
|
|
Description: Returns the session's outbox folder pointer.
|
|
|
|
Arguments:
|
|
ppOutBoxFolder - Address of pointer variable to receive pointer value.
|
|
|
|
Returns:
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
06/18/97 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CMapiSession::GetOutBoxFolder(
|
|
LPMAPIFOLDER *ppOutBoxFolder
|
|
)
|
|
{
|
|
HRESULT hr = E_POINTER;
|
|
|
|
if (NULL != m_pOutBoxFolder && NULL != ppOutBoxFolder)
|
|
{
|
|
*ppOutBoxFolder = m_pOutBoxFolder;
|
|
(*ppOutBoxFolder)->AddRef();
|
|
hr = NO_ERROR;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: CMapiSession::ResolveAddresses
|
|
|
|
Description: Resolves names in an address list.
|
|
|
|
Arguments:
|
|
pAdrList - Pointer to the address list to be resolved.
|
|
|
|
Returns:
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
06/18/97 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CMapiSession::ResolveAddresses(
|
|
LPADRLIST pAdrList
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
LPADRBOOK pAdrBook = NULL;
|
|
|
|
hr = GetAddressBook(&pAdrBook);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pAdrBook->ResolveName(0, // Hwnd for UI
|
|
0, // Flags (no UI).
|
|
NULL, // Dlg title (none).
|
|
pAdrList); // ADRLIST ptr
|
|
|
|
ReportErrorsReturned(hr);
|
|
pAdrBook->Release();
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: CMapiMessageBody::CMapiMessageBody
|
|
|
|
Description: Constructors.
|
|
|
|
Arguments:
|
|
rhs - Reference to source CMapiMessageBody object in copy ctor.
|
|
|
|
Returns: Nothing.
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
06/18/97 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
CMapiMessageBody::CMapiMessageBody(
|
|
VOID
|
|
) : m_pStg(NULL),
|
|
m_pStm(NULL)
|
|
{
|
|
CommonConstruct();
|
|
}
|
|
|
|
CMapiMessageBody::CMapiMessageBody(
|
|
const CMapiMessageBody& rhs
|
|
) : m_pStg(NULL),
|
|
m_pStm(NULL)
|
|
{
|
|
CommonConstruct();
|
|
*this = rhs;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: CMapiMessageBody::~CMapiMessageBody
|
|
|
|
Description: Destructor.
|
|
|
|
Arguments: None.
|
|
|
|
Returns: Nothing.
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
06/18/97 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
CMapiMessageBody::~CMapiMessageBody(
|
|
VOID
|
|
)
|
|
{
|
|
if (NULL != m_pStm)
|
|
{
|
|
m_pStm->Release();
|
|
}
|
|
if (NULL != m_pStg)
|
|
{
|
|
m_pStg->Release();
|
|
}
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: CMapiMessageBody::operator =
|
|
|
|
Description: Assignment operator.
|
|
|
|
Arguments:
|
|
rhs - Reference to source CMapiMessageBody object.
|
|
|
|
Returns: Reference to *this.
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
06/18/97 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
CMapiMessageBody&
|
|
CMapiMessageBody::operator = (
|
|
const CMapiMessageBody& rhs
|
|
)
|
|
{
|
|
if (this != &rhs)
|
|
{
|
|
if (NULL != m_pStm && NULL != rhs.m_pStm)
|
|
{
|
|
HRESULT hr;
|
|
LPSTREAM pStmClone;
|
|
|
|
//
|
|
// Create a clone of the source stream so that we don't alter
|
|
// the source's seek ptr.
|
|
//
|
|
hr = rhs.m_pStm->Clone(&pStmClone);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
ULARGE_INTEGER ulSize = {0, 0};
|
|
LARGE_INTEGER lSeek = {0, 0};
|
|
//
|
|
// Reset the source stream seek ptr to the beginnging.
|
|
//
|
|
pStmClone->Seek(lSeek, STREAM_SEEK_SET, NULL);
|
|
//
|
|
// Truncate the destination stream to clear it.
|
|
//
|
|
m_pStm->SetSize(ulSize);
|
|
//
|
|
// Copy all of the source stream to the dest stream.
|
|
//
|
|
ulSize.LowPart = 0xFFFFFFFF;
|
|
hr = pStmClone->CopyTo(m_pStm, // Destination stream.
|
|
ulSize, // Write all bytes.
|
|
NULL, // pcbRead
|
|
NULL); // pcbWritten
|
|
pStmClone->Release();
|
|
}
|
|
}
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: CMapiMessageBody::CommonConstruct
|
|
|
|
Description: Performs operations common to all forms of constructors.
|
|
|
|
1. Creates Storage object.
|
|
2. Creates Stream "MSGBODY" in storage.
|
|
|
|
Arguments: None.
|
|
|
|
Returns:
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
06/18/97 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CMapiMessageBody::CommonConstruct(
|
|
VOID
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
DWORD grfMode = STGM_DIRECT | STGM_READWRITE |
|
|
STGM_CREATE | STGM_SHARE_EXCLUSIVE;
|
|
//
|
|
// Create the output doc file.
|
|
//
|
|
hr = StgCreateDocfile(NULL, // Temp file with unique name.
|
|
grfMode, // Access flags.
|
|
0, // Reserved
|
|
&m_pStg); // Stg ptr (out)
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// Create the stream in the doc file.
|
|
//
|
|
hr = m_pStg->CreateStream(L"MSGBODY", // Stream name.
|
|
grfMode, // Access flags.
|
|
0, // Reserved.
|
|
0, // Reserved.
|
|
&m_pStm); // Stream ptr (out)
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: CMapiMessageBody::Append
|
|
|
|
Description: Appends text to the msg body stream. Two versions are
|
|
provided. One accepts a nul-terminated format string while the other
|
|
accepts the resource ID for a string resource. Both formats allow
|
|
variable replacement arguments for replaceable arguments in the
|
|
format strings (i.e. %1, %2 etc.)
|
|
|
|
Arguments:
|
|
hInst - Module instance handle for string/message resource.
|
|
|
|
pszFmt - Address of format string.
|
|
|
|
idFmt - ID of format resource string. May be a string or message
|
|
resource.
|
|
|
|
Returns:
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
06/18/97 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CMapiMessageBody::Append(
|
|
LPCTSTR pszFmt,
|
|
...
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
va_list args;
|
|
va_start(args, pszFmt);
|
|
|
|
hr = Append(pszFmt, &args);
|
|
|
|
va_end(args);
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CMapiMessageBody::Append(
|
|
LPCTSTR pszFmt,
|
|
va_list *pargs
|
|
)
|
|
{
|
|
HRESULT hr = E_POINTER;
|
|
|
|
if (NULL != m_pStm)
|
|
{
|
|
CString str;
|
|
if (str.Format(pszFmt, pargs))
|
|
{
|
|
hr = m_pStm->Write((LPCTSTR)str, str.LengthBytes(), NULL);
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CMapiMessageBody::Append(
|
|
HINSTANCE hInst,
|
|
UINT idFmt,
|
|
...
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
|
|
va_list(args);
|
|
va_start(args, idFmt);
|
|
|
|
hr = Append(hInst, idFmt, &args);
|
|
|
|
va_end(args);
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CMapiMessageBody::Append(
|
|
HINSTANCE hInst,
|
|
UINT idFmt,
|
|
va_list *pargs
|
|
)
|
|
{
|
|
HRESULT hr = E_POINTER;
|
|
|
|
if (NULL != m_pStm)
|
|
{
|
|
CString str;
|
|
if (str.Format(hInst, idFmt, pargs))
|
|
{
|
|
hr = m_pStm->Write((LPCTSTR)str, str.LengthBytes(), NULL);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: CMapiMessage::CMapiMessage
|
|
|
|
Description: Constructors.
|
|
|
|
Arguments:
|
|
pFolder - Address of LPMAPIFOLDER object in which the message is
|
|
to be created.
|
|
|
|
body - Reference to a CMapiMessageBody object containing text for the
|
|
body of the message.
|
|
|
|
pszSubject [optional] - Address of message subject line string.
|
|
|
|
Returns: Nothing.
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
06/18/97 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
CMapiMessage::CMapiMessage(
|
|
LPMAPIFOLDER pFolder
|
|
) : m_pMsg(NULL)
|
|
{
|
|
CommonConstruct(pFolder);
|
|
}
|
|
|
|
CMapiMessage::CMapiMessage(
|
|
LPMAPIFOLDER pFolder,
|
|
CMapiMessageBody& body,
|
|
LPCTSTR pszSubject /* optional */
|
|
) : m_pMsg(NULL),
|
|
m_body(body)
|
|
{
|
|
CommonConstruct(pFolder);
|
|
if (NULL != pszSubject)
|
|
{
|
|
SetSubject(pszSubject);
|
|
}
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: CMapiMessage::~CMapiMessage
|
|
|
|
Description: Destructor.
|
|
|
|
Arguments: None.
|
|
|
|
Returns:
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
06/18/97 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
CMapiMessage::~CMapiMessage(
|
|
VOID
|
|
)
|
|
{
|
|
if (NULL != m_pMsg)
|
|
{
|
|
m_pMsg->Release();
|
|
}
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: CMapiMessage::CommonConstruct
|
|
|
|
Description: Performs operations common to all forms of constructors.
|
|
|
|
1. Creates the MAPI message object.
|
|
2. Sets the DELETE_AFTER_SUBMIT property (common to all messages).
|
|
|
|
Arguments:
|
|
pFolder - Address of LPMAPIFOLDER object in which the message is
|
|
to be created.
|
|
|
|
Returns:
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
06/18/97 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CMapiMessage::CommonConstruct(
|
|
LPMAPIFOLDER pFolder
|
|
)
|
|
{
|
|
HRESULT hr = E_POINTER;
|
|
|
|
if (NULL != pFolder)
|
|
{
|
|
hr = pFolder->CreateMessage(NULL, 0, &m_pMsg);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// Don't want sent message hanging around in users's outbox.
|
|
//
|
|
SPropValue rgProp[1];
|
|
rgProp[0].ulPropTag = PR_DELETE_AFTER_SUBMIT;
|
|
rgProp[0].Value.b = TRUE;
|
|
|
|
hr = m_pMsg->SetProps(ARRAYSIZE(rgProp), rgProp, NULL);
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CMapiMessage::SetProps(
|
|
ULONG cValues,
|
|
LPSPropValue lpPropArray,
|
|
LPSPropProblemArray *lppProblems
|
|
)
|
|
{
|
|
HRESULT hr = E_UNEXPECTED;
|
|
if (NULL != m_pMsg)
|
|
{
|
|
hr = m_pMsg->SetProps(cValues, lpPropArray, lppProblems);
|
|
}
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CMapiMessage::SaveChanges(
|
|
ULONG ulFlags
|
|
)
|
|
{
|
|
HRESULT hr = E_UNEXPECTED;
|
|
if (NULL != m_pMsg)
|
|
{
|
|
hr = m_pMsg->SaveChanges(ulFlags);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: CMapiMessage::SetSubject
|
|
|
|
Description: Sets the PR_SUBJECT property of the message.
|
|
|
|
Arguments:
|
|
pszSubject - Address of new subject string.
|
|
|
|
Returns:
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
06/18/97 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CMapiMessage::SetSubject(
|
|
LPCTSTR pszSubject
|
|
)
|
|
{
|
|
HRESULT hr = E_POINTER;
|
|
if (NULL != m_pMsg)
|
|
{
|
|
//
|
|
// Set the msg subject text property.
|
|
//
|
|
SPropValue spvProp;
|
|
spvProp.ulPropTag = PR_SUBJECT;
|
|
spvProp.Value.LPSZ = (LPTSTR)pszSubject;
|
|
|
|
hr = m_pMsg->SetProps(1, &spvProp, NULL);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: CMapiMessage::SetRecipients
|
|
|
|
Description: Sets the recipients for the message. It is assumed that
|
|
the recipients in pAdrList have been resolved.
|
|
|
|
Arguments:
|
|
pAdrList - Address of MAPI address list containing resolved addresses.
|
|
|
|
Returns:
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
06/18/97 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CMapiMessage::SetRecipients(
|
|
LPADRLIST pAdrList
|
|
)
|
|
{
|
|
HRESULT hr = E_POINTER;
|
|
if (NULL != m_pMsg)
|
|
{
|
|
hr = m_pMsg->ModifyRecipients(0, pAdrList);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: CMapiMessage::Send
|
|
|
|
Description: Sends the message to a list of recipients.
|
|
|
|
Arguments:
|
|
pAdrList [optional] - Address of MAPI address list containing
|
|
resolved addresses. If this argument is NULL, the caller must
|
|
call SetRecipients before calling Send.
|
|
|
|
Returns:
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
06/18/97 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CMapiMessage::Send(
|
|
LPADRLIST pAdrList /* optional */
|
|
)
|
|
{
|
|
HRESULT hr = E_POINTER;
|
|
if (NULL != m_pMsg)
|
|
{
|
|
hr = NO_ERROR;
|
|
if (NULL != pAdrList)
|
|
{
|
|
//
|
|
// If there's an address list, set the recipients.
|
|
// If not, the caller must call SetRecipients before calling Send().
|
|
// Otherwise, there will be no recipients to send it to.
|
|
//
|
|
hr = SetRecipients(pAdrList);
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
LPSTREAM pPropStream;
|
|
hr = m_pMsg->OpenProperty(PR_BODY,
|
|
&IID_IStream,
|
|
STGM_READWRITE | STGM_DIRECT,
|
|
MAPI_CREATE | MAPI_MODIFY,
|
|
(LPUNKNOWN *)&pPropStream);
|
|
if (S_OK == hr)
|
|
{
|
|
LPSTREAM pMsgBodyStm = (LPSTREAM)m_body;
|
|
LPSTREAM pMsgBodyStmClone;
|
|
|
|
//
|
|
// Clone the body stream so that we don't alter it's seek ptr.
|
|
//
|
|
hr = pMsgBodyStm->Clone(&pMsgBodyStmClone);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
ULARGE_INTEGER ulSize = {0xFFFFFFFF, 0};
|
|
LARGE_INTEGER lSeek = {0, 0};
|
|
|
|
//
|
|
// Copy the msg body stream to the PR_BODY property.
|
|
//
|
|
pMsgBodyStmClone->Seek(lSeek, STREAM_SEEK_SET, NULL);
|
|
pMsgBodyStmClone->CopyTo(pPropStream, ulSize, NULL, NULL);
|
|
pPropStream->Commit(STGC_DEFAULT);
|
|
//
|
|
// Release temp streams.
|
|
//
|
|
pPropStream->Release();
|
|
pMsgBodyStmClone->Release();
|
|
//
|
|
// Send it!
|
|
// Note: Calling SaveChanges() is not required if the message
|
|
// is being sent immediately.
|
|
//
|
|
hr = m_pMsg->SubmitMessage(FORCE_SUBMIT);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: CMapiMessage::Append
|
|
|
|
Description: Appends text to the msg body stream. Two versions are
|
|
provided. One accepts a nul-terminated format string while the other
|
|
accepts the resource ID for a string resource. Both formats allow
|
|
variable replacement arguments for replaceable arguments in the
|
|
format strings (i.e. %1, %2 etc.)
|
|
|
|
Arguments:
|
|
hInst - Module instance handle for string/message resource.
|
|
|
|
pszFmt - Address of format string.
|
|
|
|
idFmt - ID of format resource string. May be a string or message
|
|
resource.
|
|
|
|
Returns:
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
06/18/97 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CMapiMessage::Append(
|
|
LPCTSTR pszFmt,
|
|
...
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
|
|
va_list args;
|
|
va_start(args, pszFmt);
|
|
hr = m_body.Append(pszFmt, &args);
|
|
va_end(args);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CMapiMessage::Append(
|
|
HINSTANCE hInst,
|
|
UINT idFmt,
|
|
...
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
|
|
va_list(args);
|
|
va_start(args, idFmt);
|
|
hr = m_body.Append(hInst, idFmt, &args);
|
|
va_end(args);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Static members of class MAPI.
|
|
//
|
|
LONG MAPI::m_cLoadCount;
|
|
HINSTANCE MAPI::m_hmodMAPI;
|
|
LPMAPIINITIALIZE MAPI::m_pfnInitialize;
|
|
LPMAPILOGONEX MAPI::m_pfnLogonEx;
|
|
LPMAPIUNINITIALIZE MAPI::m_pfnUninitialize;
|
|
LPMAPIALLOCATEBUFFER MAPI::m_pfnAllocateBuffer;
|
|
LPMAPIALLOCATEMORE MAPI::m_pfnAllocateMore;
|
|
LPMAPIFREEBUFFER MAPI::m_pfnFreeBuffer;
|
|
LPMAPIHRQUERYALLROWS MAPI::m_pfnHrQueryAllRows;
|
|
LPMAPIFREEPADRLIST MAPI::m_pfnFreePadrlist;
|
|
LPMAPIFREEPROWS MAPI::m_pfnFreeProws;
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: MAPI::MAPI
|
|
|
|
Description: Constructor.
|
|
|
|
Arguments: None.
|
|
|
|
Returns:
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
06/22/97 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
MAPI::MAPI(
|
|
VOID
|
|
)
|
|
{
|
|
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: MAPI::~MAPI
|
|
|
|
Description: Destructor. Ensures MAPI32.DLL is unloaded.
|
|
|
|
Arguments: None.
|
|
|
|
Returns:
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
06/22/97 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
MAPI::~MAPI(
|
|
VOID
|
|
)
|
|
{
|
|
//
|
|
// m_cLoadCount should be 0 at this point if calls to Load() and
|
|
// Unload() are balanced.
|
|
//
|
|
ASSERT(0 == m_cLoadCount);
|
|
if (0 < m_cLoadCount)
|
|
{
|
|
//
|
|
// Calls to Load() and Unload() are not balanced due to programmer
|
|
// error or maybe an exception preventing a call to Unload().
|
|
// This will force Unload to call FreeLibrary().
|
|
//
|
|
m_cLoadCount = 1;
|
|
}
|
|
Unload();
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: MAPI::Load
|
|
|
|
Description: Load MAPI32.DLL and call GetProcAddress for all of the
|
|
MAPI32 functions we're interested in using. Maintains a reference
|
|
count so redundant calls to LoadLibrary are avoided.
|
|
|
|
Arguments: None.
|
|
|
|
Returns:
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
06/22/97 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
MAPI::Load(
|
|
VOID
|
|
)
|
|
{
|
|
Assert(0 <= m_cLoadCount);
|
|
if (0 == m_cLoadCount++)
|
|
{
|
|
m_hmodMAPI = ::LoadLibrary(TEXT("MAPI32.DLL"));
|
|
if (NULL != m_hmodMAPI)
|
|
{
|
|
m_pfnInitialize = (LPMAPIINITIALIZE) ::GetProcAddress(m_hmodMAPI, "MAPIInitialize");
|
|
m_pfnLogonEx = (LPMAPILOGONEX) ::GetProcAddress(m_hmodMAPI, "MAPILogonEx");
|
|
m_pfnUninitialize = (LPMAPIUNINITIALIZE) ::GetProcAddress(m_hmodMAPI, "MAPIUninitialize");
|
|
m_pfnAllocateBuffer = (LPMAPIALLOCATEBUFFER)::GetProcAddress(m_hmodMAPI, "MAPIAllocateBuffer");
|
|
m_pfnAllocateMore = (LPMAPIALLOCATEMORE) ::GetProcAddress(m_hmodMAPI, "MAPIAllocateMore");
|
|
m_pfnFreeBuffer = (LPMAPIFREEBUFFER) ::GetProcAddress(m_hmodMAPI, "MAPIFreeBuffer");
|
|
m_pfnHrQueryAllRows = (LPMAPIHRQUERYALLROWS)::GetProcAddress(m_hmodMAPI, "HrQueryAllRows@24");
|
|
m_pfnFreePadrlist = (LPMAPIFREEPADRLIST) ::GetProcAddress(m_hmodMAPI, "FreePadrlist@4");
|
|
m_pfnFreeProws = (LPMAPIFREEPROWS) ::GetProcAddress(m_hmodMAPI, "FreeProws@4");
|
|
}
|
|
}
|
|
return (NULL != m_hmodMAPI) ? NO_ERROR : E_FAIL;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: MAPI::Unload
|
|
|
|
Description: Unloads MAPI32.DLL if the reference count drops to 0. If
|
|
the library is unloaded, all of the function pointers are
|
|
set to NULL.
|
|
|
|
Arguments: None.
|
|
|
|
Returns:
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
06/22/97 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
VOID
|
|
MAPI::Unload(
|
|
VOID
|
|
)
|
|
{
|
|
ASSERT(0 < m_cLoadCount);
|
|
if (0 == --m_cLoadCount)
|
|
{
|
|
if (NULL != m_hmodMAPI)
|
|
{
|
|
::FreeLibrary(m_hmodMAPI);
|
|
m_hmodMAPI = NULL;
|
|
}
|
|
m_pfnInitialize = NULL;
|
|
m_pfnLogonEx = NULL;
|
|
m_pfnUninitialize = NULL;
|
|
m_pfnAllocateBuffer = NULL;
|
|
m_pfnAllocateMore = NULL;
|
|
m_pfnFreeBuffer = NULL;
|
|
m_pfnHrQueryAllRows = NULL;
|
|
m_pfnFreePadrlist = NULL;
|
|
m_pfnFreeProws = NULL;
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// The remaining MAPI::XXXX functions are merely simple wrappers around the
|
|
// corresponding functions in MAPI32.DLL.
|
|
// See the MAPI SDK for information concerning their use.
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
HRESULT
|
|
MAPI::LogonEx(
|
|
ULONG ulUIParam,
|
|
LPTSTR lpszProfileName,
|
|
LPTSTR lpszPassword,
|
|
FLAGS flFlags,
|
|
LPMAPISESSION FAR * lppSession
|
|
)
|
|
{
|
|
ASSERT(NULL != m_pfnLogonEx);
|
|
if (NULL != m_pfnLogonEx)
|
|
return (*m_pfnLogonEx)(ulUIParam, lpszProfileName, lpszPassword, flFlags, lppSession);
|
|
else
|
|
return E_POINTER;
|
|
}
|
|
|
|
HRESULT
|
|
MAPI::Initialize(
|
|
LPVOID lpMapiInit
|
|
)
|
|
{
|
|
ASSERT(NULL != m_pfnInitialize);
|
|
if (NULL != m_pfnInitialize)
|
|
return (*m_pfnInitialize)(lpMapiInit);
|
|
else
|
|
return E_POINTER;
|
|
}
|
|
|
|
|
|
VOID
|
|
MAPI::Uninitialize(
|
|
VOID
|
|
)
|
|
{
|
|
ASSERT(NULL != m_pfnUninitialize);
|
|
if (NULL != m_pfnUninitialize)
|
|
(*m_pfnUninitialize)();
|
|
}
|
|
|
|
|
|
|
|
SCODE
|
|
MAPI::AllocateBuffer(
|
|
ULONG cbSize,
|
|
LPVOID FAR * lppBuffer
|
|
)
|
|
{
|
|
ASSERT(NULL != m_pfnAllocateBuffer);
|
|
if (NULL != m_pfnAllocateBuffer)
|
|
return (*m_pfnAllocateBuffer)(cbSize, lppBuffer);
|
|
else
|
|
return E_POINTER;
|
|
}
|
|
|
|
|
|
SCODE
|
|
MAPI::AllocateMore(
|
|
ULONG cbSize,
|
|
LPVOID lpObject,
|
|
LPVOID FAR * lppBuffer
|
|
)
|
|
{
|
|
ASSERT(NULL != m_pfnAllocateMore);
|
|
if (NULL != m_pfnAllocateMore)
|
|
return (*m_pfnAllocateMore)(cbSize, lpObject, lppBuffer);
|
|
else
|
|
return E_POINTER;
|
|
}
|
|
|
|
|
|
ULONG
|
|
MAPI::FreeBuffer(
|
|
LPVOID lpBuffer
|
|
)
|
|
{
|
|
ASSERT(NULL != m_pfnFreeBuffer);
|
|
if (NULL != m_pfnFreeBuffer)
|
|
return (*m_pfnFreeBuffer)(lpBuffer);
|
|
else
|
|
return (ULONG)E_POINTER;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
MAPI::HrQueryAllRows(
|
|
LPMAPITABLE lpTable,
|
|
LPSPropTagArray lpPropTags,
|
|
LPSRestriction lpRestriction,
|
|
LPSSortOrderSet lpSortOrderSet,
|
|
LONG crowsMax,
|
|
LPSRowSet FAR *lppRows
|
|
)
|
|
{
|
|
ASSERT(NULL != m_pfnHrQueryAllRows);
|
|
if (NULL != m_pfnHrQueryAllRows)
|
|
return (*m_pfnHrQueryAllRows)(lpTable,
|
|
lpPropTags,
|
|
lpRestriction,
|
|
lpSortOrderSet,
|
|
crowsMax,
|
|
lppRows);
|
|
else
|
|
return E_POINTER;
|
|
}
|
|
|
|
|
|
VOID
|
|
MAPI::FreePadrlist(
|
|
LPADRLIST lpAdrList
|
|
)
|
|
{
|
|
ASSERT(NULL != m_pfnFreePadrlist);
|
|
if (NULL != m_pfnFreePadrlist)
|
|
(*m_pfnFreePadrlist)(lpAdrList);
|
|
}
|
|
|
|
|
|
VOID
|
|
MAPI::FreeProws(
|
|
LPSRowSet lpRows
|
|
)
|
|
{
|
|
ASSERT(NULL != m_pfnFreeProws);
|
|
if (NULL != m_pfnFreeProws)
|
|
(*m_pfnFreeProws)(lpRows);
|
|
}
|
|
|