Outlook profile - multiple message service for Exchange

  • Thread starter Thread starter gbalci1974
  • Start date Start date
G

gbalci1974

Guest
Hello,

I don't have any experience in C++ and I need to create a console application to create one Outlook profile with two message service for Exchange

Why C++? Since Outlook 2016 PRF files are no more supported and Extended MAPI needs to be used

Found the following code on Microsoft Website

Programmatically create a profile in Outlook

I changed the code to include tow emails instead of one but having an issue with CreateMsgService

Basically the second message service is created but empty

Copied the code at the end of this message

Thank you for your help

Goksel

// CreateProfile.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <Windows.h>
#include <MAPIX.h>
#include <MAPIUtil.h>
#include <EdkMdb.h>
#include <iostream>
#include <vector>
#include <map>
using namespace std;
#define PR_PROFILE_USER_SMTP_EMAIL_ADDRESS1 PROP_TAG(PT_TSTRING, pidProfileMin+0x41)
#define PR_PROFILE_USER_SMTP_EMAIL_ADDRESS1_W PROP_TAG(PT_UNICODE, pidProfileMin+0x41)
#define PR_PROFILE_USER_SMTP_EMAIL_ADDRESS2 PROP_TAG(PT_TSTRING, pidProfileMin+0x41)
#define PR_PROFILE_USER_SMTP_EMAIL_ADDRESS2_W PROP_TAG(PT_UNICODE, pidProfileMin+0x41)
#define PR_EMSMDB_SECTION_UID PROP_TAG(PT_BINARY, 0x3D15)
#define MAPI_FORCE_ACCESS 0x80000
STDMETHODIMP GetGlobalProfileSection(LPSERVICEADMIN lpSvcAdmin, LPMAPIUID lpMapiUid, ULONG ulFlags, LPPROFSECT * lppProfSect);
STDMETHODIMP GetEMSMDBVarProfileSection(LPSERVICEADMIN lpSvcAdmin, LPPROFSECT lpGlobalProfSection, LPPROFSECT * lppProfSect);
std::map<ULONG, LPWSTR> PropValueMap1
{
{
PR_DISPLAY_NAME_W,
L"MAILBOX1"
},
{
PR_PROFILE_USER_SMTP_EMAIL_ADDRESS1_W,
L"=SMTP:mailbox1@contoso.com"
}
};
std::map<ULONG, LPWSTR> PropValueMap2
{
{
PR_DISPLAY_NAME_W,
L"MAILBOX2"
},
{
PR_PROFILE_USER_SMTP_EMAIL_ADDRESS2_W,
L"=SMTP:mailbox2@contoso.com"
}
};
int _tmain(int argc, _TCHAR* argv[])
{
HRESULT hRes = S_OK; // Result from MAPI calls.
LPPROFADMIN lpProfAdmin = NULL; // Profile Admin object.
LPSERVICEADMIN lpSvcAdmin = NULL; // Service Admin object.
LPMAPITABLE lpMsgSvcTable = NULL; // Table to hold services.
LPSRowSet lpSvcRows = NULL; // Rowset to hold results of table query.
vector<SPropValue> rgvals;
SRestriction sres; // Restriction structure.
SPropValue SvcProps; // Property structure for restriction.
LPPROFSECT lpGlobalProfSection = nullptr;
LPPROFSECT lpEmsMdbVarProfSect = nullptr;
SPropValue spvSmtpAddressW;
SPropValue spvDisplayName;
// This indicates columns we want returned from HrQueryAllRows.
enum { iSvcName, iSvcUID, cptaSvc };
SizedSPropTagArray(cptaSvc, sptCols) = { cptaSvc, PR_SERVICE_NAME, PR_SERVICE_UID };
string ProfileName = "SMS";
// Initialize MAPI.
if (FAILED(hRes = MAPIInitialize(NULL)))
{
cout << "Error initializing MAPI.";
goto error;
}
// Get an IProfAdmin interface.
if (FAILED(hRes = MAPIAdminProfiles(0, // Flags.
&lpProfAdmin))) // Pointer to new IProfAdmin.
{
cout << "Error getting IProfAdmin interface.";
goto error;
}
// Create a new profile.
if (FAILED(hRes = lpProfAdmin->CreateProfile((LPTSTR)ProfileName.c_str(), // Name of new profile.
nullptr, // Password for profile.
0, // Handle to parent window.
0))) // Flags.
{
cout << "Error creating profile.";
goto error;
}
// Get an IMsgServiceAdmin interface off of the IProfAdmin interface.
if (FAILED(hRes = lpProfAdmin->AdminServices((LPTSTR)ProfileName.c_str(), // Profile that we want to modify.
nullptr, // Password for that profile.
0, // Handle to parent window.
0, // Flags.
&lpSvcAdmin))) // Pointer to new IMsgServiceAdmin.
{
cout << "Error getting IMsgServiceAdmin interface.";
goto error;
}
// Create the new message service for Exchange.
if (FAILED(hRes = lpSvcAdmin->CreateMsgService("MSEMS", // Name of service from MAPISVC.INF.
NULL, // Display name of service.
NULL, // Handle to parent window.
NULL))) // Flags.
{
cout << "Error creating Exchange message service.";
goto error;
}
// You now have to obtain the entry id for the new service.
// You can do this by getting the message service table
// and getting the entry that corresponds to the new service.
if (FAILED(hRes = lpSvcAdmin->GetMsgServiceTable(0, // Flags.
&lpMsgSvcTable))) // Pointer to table.
{
cout << "Error getting Message Service Table.";
goto error;
}
// Set up restriction to query table.
sres.rt = RES_CONTENT;
sres.res.resContent.ulFuzzyLevel = FL_FULLSTRING;
sres.res.resContent.ulPropTag = PR_SERVICE_NAME;
sres.res.resContent.lpProp = &SvcProps;
SvcProps.ulPropTag = PR_SERVICE_NAME;
SvcProps.Value.lpszA = "MSEMS";
// Query the table to obtain the entry for the newly created message service.
if (FAILED(hRes = HrQueryAllRows(lpMsgSvcTable,
(LPSPropTagArray)&sptCols,
&sres,
NULL,
0,
&lpSvcRows)))
{
cout << "Error querying table for new message service.";
goto error;
}
ZeroMemory(&spvSmtpAddressW, sizeof(spvSmtpAddressW));
spvSmtpAddressW.ulPropTag = PR_PROFILE_USER_SMTP_EMAIL_ADDRESS1_W;
spvSmtpAddressW.Value.lpszW = PropValueMap1[PR_PROFILE_USER_SMTP_EMAIL_ADDRESS1_W];
rgvals.push_back(spvSmtpAddressW);
if (FAILED(hRes = GetGlobalProfileSection(
lpSvcAdmin,
(LPMAPIUID)lpSvcRows->aRow->lpProps[iSvcUID].Value.bin.lpb,
MAPI_MODIFY,
&lpGlobalProfSection)))
{
cout << "Error attempting to get the Global Profile Section.";
goto error;
}
if (FAILED(hRes = lpGlobalProfSection->SetProps(
rgvals.size(),
rgvals.data(),
nullptr)))
{
cout << "Error attempting to set the smtp address.";
goto error;
}
if (FAILED(hRes = lpGlobalProfSection->SaveChanges(
KEEP_OPEN_READWRITE)))
{
cout << "Error attempting to save after setting the smtp address";
goto error;
}
if (FAILED(hRes = GetEMSMDBVarProfileSection(lpSvcAdmin, lpGlobalProfSection, &lpEmsMdbVarProfSect)))
{
goto error;
}
ZeroMemory(&spvDisplayName, sizeof(spvDisplayName));
spvDisplayName.ulPropTag = PR_DISPLAY_NAME_W;
spvDisplayName.Value.lpszW = PropValueMap1[PR_DISPLAY_NAME_W];
rgvals.push_back(spvDisplayName);
if (FAILED(hRes = lpEmsMdbVarProfSect->SetProps(
rgvals.size(),
rgvals.data(),
nullptr)))
{
cout << "Error call set props on the ems mdb var prof sect using the smtp address";
goto error;
}
if (FAILED(hRes = lpEmsMdbVarProfSect->SaveChanges(
KEEP_OPEN_READWRITE)))
{
cout << "Error attempting to save after setting the smtp address on the ems mdb var prof sect";
goto error;
}


// Create the new message service for Exchange.
if (FAILED(hRes = lpSvcAdmin->CreateMsgService("MSEMS", // Name of service from MAPISVC.INF.
NULL, // Display name of service.
NULL, // Handle to parent window.
NULL))) // Flags.
{
cout << "Error creating Exchange message service.";
goto error;
}

ZeroMemory(&spvSmtpAddressW, sizeof(spvSmtpAddressW));
spvSmtpAddressW.ulPropTag = PR_PROFILE_USER_SMTP_EMAIL_ADDRESS2_W;
spvSmtpAddressW.Value.lpszW = PropValueMap2[PR_PROFILE_USER_SMTP_EMAIL_ADDRESS2_W];
rgvals.push_back(spvSmtpAddressW);

if (FAILED(hRes = GetGlobalProfileSection(
lpSvcAdmin,
(LPMAPIUID)lpSvcRows->aRow->lpProps[iSvcUID].Value.bin.lpb,
MAPI_MODIFY,
&lpGlobalProfSection)))
{
cout << "Error attempting to get the Global Profile Section.";
goto error;
}
if (FAILED(hRes = lpGlobalProfSection->SetProps(
rgvals.size(),
rgvals.data(),
nullptr)))
{
cout << "Error attempting to set the smtp address.";
goto error;
}
if (FAILED(hRes = lpGlobalProfSection->SaveChanges(
KEEP_OPEN_READWRITE)))
{
cout << "Error attempting to save after setting the smtp address";
goto error;
}

if (FAILED(hRes = GetEMSMDBVarProfileSection(lpSvcAdmin, lpGlobalProfSection, &lpEmsMdbVarProfSect)))
{
goto error;
}
ZeroMemory(&spvDisplayName, sizeof(spvDisplayName));
spvDisplayName.ulPropTag = PR_DISPLAY_NAME_W;
spvDisplayName.Value.lpszW = PropValueMap2[PR_DISPLAY_NAME_W];
rgvals.push_back(spvDisplayName);
if (FAILED(hRes = lpEmsMdbVarProfSect->SetProps(
rgvals.size(),
rgvals.data(),
nullptr)))
{
cout << "Error call set props on the ems mdb var prof sect using the smtp address";
goto error;
}
if (FAILED(hRes = lpEmsMdbVarProfSect->SaveChanges(
KEEP_OPEN_READWRITE)))
{
cout << "Error attempting to save after setting the smtp address on the ems mdb var prof sect";
goto error;
}

cleanup:
// Clean up
if (lpEmsMdbVarProfSect) lpEmsMdbVarProfSect->Release();
if (lpGlobalProfSection) lpGlobalProfSection->Release();
if (lpSvcRows) FreeProws(lpSvcRows);
if (lpMsgSvcTable) lpMsgSvcTable->Release();
if (lpSvcAdmin) lpSvcAdmin->Release();
if (lpProfAdmin) lpProfAdmin->Release();
MAPIUninitialize();
return 0;
error:
cout << " hRes = 0x" << hex << hRes << dec << endl;
goto cleanup;
}
STDMETHODIMP GetGlobalProfileSection(LPSERVICEADMIN lpSvcAdmin, LPMAPIUID lpMapiUid, ULONG ulFlags, LPPROFSECT * lppProfSect)
{
HRESULT hRes = MAPI_E_CALL_FAILED;
LPPROFSECT lpProfSect = nullptr;
LPPROFSECT lpEmsMdbVarProfSect = nullptr;
ULONG cValues = 0;
LPSPropValue lpProps = nullptr;
SizedSPropTagArray(1, spta) = { 1,{ PR_EMSMDB_SECTION_UID } };
*lppProfSect = nullptr;
hRes = lpSvcAdmin->OpenProfileSection(lpMapiUid,
0,
MAPI_FORCE_ACCESS,
&lpProfSect);
if (FAILED(hRes) || lpProfSect == nullptr)
{
return hRes;
}
hRes = lpProfSect->GetProps((LPSPropTagArray)&spta, 0, &cValues, &lpProps);
if (FAILED(hRes) || lpProps == nullptr || cValues == 0)
{
return hRes;
}
if (lpProps[0].ulPropTag != PR_EMSMDB_SECTION_UID)
{
hRes = lpProps[0].Value.err;
goto Cleanup;
}
hRes = lpSvcAdmin->OpenProfileSection((LPMAPIUID)lpProps->Value.bin.lpb, 0, ulFlags, &lpEmsMdbVarProfSect);
if (FAILED(hRes) || lpEmsMdbVarProfSect == nullptr)
{
goto Cleanup;
}
*lppProfSect = lpEmsMdbVarProfSect;
Cleanup:
if (lpProps)
{
MAPIFreeBuffer(lpProps);
}
if (lpProfSect)
{
lpProfSect->Release();
}
return hRes;
}
STDMETHODIMP GetEMSMDBVarProfileSection(LPSERVICEADMIN lpSvcAdmin, LPPROFSECT lpGlobalProfSection, LPPROFSECT * lppProfSect)
{
HRESULT hRes = MAPI_E_CALL_FAILED;
SizedSPropTagArray(1, sptaStoreProviders) = { 1,{ PR_STORE_PROVIDERS } };
ULONG cValues = 0;
LPSPropValue lpProps = nullptr;
LPPROFSECT lpProfSect = nullptr;
if (!lpSvcAdmin || !lpGlobalProfSection || !lppProfSect)
return E_INVALIDARG;
*lppProfSect = nullptr;
if (FAILED(hRes = lpGlobalProfSection->GetProps(
(LPSPropTagArray)&sptaStoreProviders,
0,
&cValues,
&lpProps)) || cValues == 0 || lpProps == nullptr)
{
cout << "Error attempting to get the PR_STORE_PROVIDERS property " << endl;
goto Cleanup;
}
if (lpProps->ulPropTag != sptaStoreProviders.aulPropTag[0])
{
hRes = lpProps->Value.err;
goto Cleanup;
}
if (FAILED(hRes = lpSvcAdmin->OpenProfileSection(
(LPMAPIUID)lpProps->Value.bin.lpb,
0,
MAPI_FORCE_ACCESS | MAPI_MODIFY,
&lpProfSect)) || lpProfSect == nullptr)
{
cout << "Could not open the profile section using the PR_STORE_PROVIDERS property " << endl;
goto Cleanup;
}
*lppProfSect = lpProfSect;
Cleanup:
if (lpProps)
{
MAPIFreeBuffer(lpProps);
lpProps = nullptr;
}
return hRes;
}

Continue reading...
 
Back
Top