this is code sample from MFCMAPI
#include <windows.h>
// clang-format off
#pragma warning(disable : 26426) // Warning C26426 Global initializer calls a non-constexpr (i.22)
#pragma warning(disable : 26446) // Warning C26446 Prefer to use gsl::at() instead of unchecked subscript operator (bounds.4).
#pragma warning(disable : 26481) // Warning C26481 Don't use pointer arithmetic. Use span instead (bounds.1).
#pragma warning(disable : 26485) // Warning C26485 Expression '': No array to pointer decay (bounds.3).
#pragma warning(disable : 26487) // Warning C26487 Don't return a pointer '' that may be invalid (lifetime.4).
// clang-format on
#include <mapix.h>
#include <mapiutil.h>
#include <mapiaux.h>
#include <mapi.h>
#include <atlbase.h>
#include <list>
#include <iostream>
#include <iomanip>
#pragma warning(disable : 4127)
#define CORg(_hr) \
hr = _hr; \
if (FAILED(hr)) \
{ \
std::wcout << L"FAILED! hr = " << std::hex << hr << L". LINE = " << std::dec << __LINE__ << std::endl; \
std::wcout << L" >>> " << (wchar_t*) L#_hr << std::endl; \
goto Error; \
} \
else \
{ \
std::wcout << L"Successed! hr = " << std::hex << hr << L". LINE = " << std::dec << __LINE__ << std::endl; \
std::wcout << L" >>> " << (wchar_t*) L#_hr << std::endl; \
}
#define CORg2(_hr) \
hr = _hr; \
if (FAILED(hr)) \
{ \
std::wcout << L"FAILED! hr = " << std::hex << hr << L". LINE = " << std::dec << __LINE__ << std::endl; \
std::wcout << L" >>> " << (wchar_t*) L#_hr << std::endl; \
} \
else \
{ \
std::wcout << L"Successed! hr = " << std::hex << hr << L". LINE = " << std::dec << __LINE__ << std::endl; \
std::wcout << L" >>> " << (wchar_t*) L#_hr << std::endl; \
}
#define EC_MAPI_S(fnx) \
[&]() -> void { \
const auto __hRes = (fnx); \
error::LogFunctionCall(__hRes, {}, true, true, false, NULL, #fnx, __FILE__, __LINE__); \
}()
#define EC_H_IGNORE_RET_MAPI(__ignore, fnx) \
error::CheckMe([&]() -> HRESULT { \
const auto __hRes = (fnx); \
error::LogFunctionCall(__hRes, __ignore, true, true, false, NULL, #fnx, __FILE__, __LINE__); \
return __hRes; \
}())
_Check_return_ LPMDB
CallOpenMsgStore(_In_ LPMAPISESSION lpSession, _In_ ULONG_PTR ulUIParam, _In_ const SBinary* lpEID, ULONG ulFlags)
{
if (!lpSession || !lpEID) return nullptr;
// if (registry::forceMDBOnline)
// {
// ulFlags |= MDB_ONLINE;
// }
// output::DebugPrint(output::dbgLevel::OpenItemProp, L"CallOpenMsgStore ulFlags = 0x%X\n", ulFlags);
LPMDB lpMDB = nullptr;
auto ignore = std::list<HRESULT>{(ulFlags & MDB_ONLINE) ? MAPI_E_UNKNOWN_FLAGS : S_OK};
HRESULT hr;
CORg2(lpSession->OpenMsgStore(
ulUIParam, lpEID->cb, reinterpret_cast<LPENTRYID>(lpEID->lpb), nullptr, ulFlags, static_cast<LPMDB*>(&lpMDB)));
if (hr == MAPI_E_UNKNOWN_FLAGS && (ulFlags & MDB_ONLINE))
{
// Perhaps this store doesn't know the MDB_ONLINE flag - remove and retry
ulFlags = ulFlags & ~MDB_ONLINE;
// output::DebugPrint(output::dbgLevel::OpenItemProp, L"CallOpenMsgStore 2nd attempt ulFlags = 0x%X\n", ulFlags);
CORg2(lpSession->OpenMsgStore(
ulUIParam,
lpEID->cb,
reinterpret_cast<LPENTRYID>(lpEID->lpb),
nullptr,
ulFlags,
static_cast<LPMDB*>(&lpMDB)));
}
return lpMDB;
}
inline const SBinary& getBin(_In_ const _SPropValue* prop) noexcept { return prop->Value.bin; }
_Check_return_ LPMDB OpenDefaultMessageStore(_In_ LPMAPISESSION lpMAPISession)
{
if (!lpMAPISession) return nullptr;
LPMAPITABLE pStoresTbl = nullptr;
LPSRowSet pRow = nullptr;
static SRestriction sres;
SPropValue spv = {};
enum
{
EID,
NUM_COLS
};
static const SizedSPropTagArray(NUM_COLS, sptEIDCol) = {
NUM_COLS,
{PR_ENTRYID},
};
lpMAPISession->GetMsgStoresTable(0, &pStoresTbl);
// set up restriction for the default store
sres.rt = RES_PROPERTY; // gonna compare a property
sres.res.resProperty.relop = RELOP_EQ; // gonna test equality
sres.res.resProperty.ulPropTag = PR_DEFAULT_STORE; // tag to compare
sres.res.resProperty.lpProp = &spv; // prop tag to compare against
spv.ulPropTag = PR_DEFAULT_STORE; // tag type
spv.Value.b = true; // tag value
HrQueryAllRows(
pStoresTbl, // table to query
LPSPropTagArray(&sptEIDCol), // columns to get
&sres, // restriction to use
nullptr, // sort order
0, // max number of rows - 0 means ALL
&pRow);
LPMDB lpDefaultMDB = nullptr;
if (pRow && pRow->cRows)
{
lpDefaultMDB = CallOpenMsgStore(lpMAPISession, NULL, &getBin(&pRow->aRow[0].lpProps[EID]), MDB_WRITE);
}
if (pRow) FreeProws(pRow);
if (pStoresTbl) pStoresTbl->Release();
return lpDefaultMDB;
}
int __cdecl main()
{
HRESULT hr = S_OK;
MAPIINIT_0 MAPIINIT = {0, MAPI_MULTITHREAD_NOTIFICATIONS};/*MAPI_NT_SERVICE*/
CORg(MAPIInitialize(&MAPIINIT));
{ // IMAPISession Smart Pointer Context
CComPtr<IMAPISession> spSession;
CORg(MAPILogonEx(
NULL,
nullptr,
nullptr,
MAPI_EXTENDED | MAPI_UNICODE | MAPI_NEW_SESSION | MAPI_USE_DEFAULT,
&spSession));
const LPMDB lpMDB = OpenDefaultMessageStore(spSession);
if(lpMDB) lpMDB->Release();
}
MAPIUninitialize();
Error:
return 0;
}