The Extended MAPI failed in window service.

Ilia Vorobyov 1 Reputation point
2022-04-17T04:50:48.503+00:00

I use Extended MAPI in my Windows 32-bit Console Application to send mail. Microsoft Outlook 2019 32-bit is installed on my computer.
It works in interactive session, but does not in non-interactive session (in window service).
The Extended MAPI OpenMsgStore failed with MAPI_E_FAILONEPROVIDER error.
The service logon user name is same as the user under which my application is working.

Office Development
Office Development
Office: A suite of Microsoft productivity software that supports common business tasks, including word processing, email, presentations, and data management and analysis.Development: The process of researching, productizing, and refining new or existing technologies.
3,720 questions
Outlook Management
Outlook Management
Outlook: A family of Microsoft email and calendar products.Management: The act or process of organizing, handling, directing or controlling something.
5,072 questions
0 comments No comments
{count} votes

5 answers

Sort by: Most helpful
  1. Eugene Astafiev 891 Reputation points
    2022-04-17T15:59:31.817+00:00

    Could you be more specific? What code exactly do you use to initialize a MAPI session?

    The MAPI_NT_SERVICE should be used if your client is implemented as a Windows service. If your client is a Windows service and you do not set this flag, MAPI will not recognize it as a service.

    0 comments No comments

  2. Ilia Vorobyov 1 Reputation point
    2022-04-17T16:07:39.86+00:00

    I tried to initialize MAPI with MAPI_NT_SERVICE and without MAPI_NT_SERVICE. Both cases failed in OpenMsgStore.

    0 comments No comments

  3. Eugene Astafiev 891 Reputation points
    2022-04-17T16:14:39.28+00:00

  4. Ilia Vorobyov 1 Reputation point
    2022-04-19T04:37:06.193+00:00

    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;
    }
    
    0 comments No comments

  5. Jas Singh Atwal 0 Reputation points
    2023-02-25T07:44:03+00:00

    Is there any movement on this issue? I'm experiencing this very issue - I'm able to open the default message store in interactive mode however, it fails with MAPI_E_FAILONEPROVIDER when ran in non-interactive mode. I'm using Outlook 2019 32-bit with an O365/M365/Exchange Online account.

    One thing I've noticed is that IMAPISession::GetStatusTable returns the following resources in interactive mode:

    • Microsoft Outlook Address Book Provider
    • Microsoft Exchange Directory Service
    • MAPI 1.0 Address Book
    • Default (name of my MAPI profile)
    • MAPI 1.0 Spooler

    But in non-interactive mode, Microsoft Exchange Directory Service is missing.

    0 comments No comments