Re: OpenMsgStore returning MAPI_E_UNCONFIGURED
- From: "Richard Glanville" <fredfredfred@xxxxxxxxxxxxx>
- Date: Thu, 22 Sep 2005 08:13:03 -0700
Hi,
I am still having problems with creating valid Unicode PSTs when the code
holds an active Exchange mailbox pointer.
The test program creates a profile and associated PST at each test point,
the source code is included below. Profiles that use an ASCII PSTs are called
A0, A1, etc. Profiles that use Unicode PSTs are called U0, U1, etc. All the
ASCII PST profiles are usable regardless of the test point at which they were
created. However the Unicode PST profiles U2 and U4 are not usable - the call
to OpenMsgStore fails. Both of these profiles are created when there is an
active Exchange mailbox pointer.
I have been investigating the differences (in the registry) between the
profiles that work and the ones that do not.
The key difference seems to be that the ones that do not work are missing a
property {PT_LONG, 0x6770} under the same registry key that that holds the
PST filename.
e.g Under.
HKEY_USERS\{SID}\Software\Microsoft\Windows NT\CurrentVersion\Windows
Messaging Subsystem\Profiles\U2\34ef82e28e528c49b6bc2ee1d6e41787
The test code contains a section that is #ifdef on FIX_THE_PROBLEM which
sets this property directly in the registry after the call to
ConfigureMsgService – with this code in place the Unicode PST can be
successfully opened at all the test points. I have been unable to set this
property using MAPI calls.
Do you have any idea what the 0x6770 property is, and why it’s not being set
when the profile is being created whilst there is an active Exchange mailbox
pointer?
Thanks,
Richard.
== Here is the test source code that I have been using with the Outlook 2003
version of MAPI
#include "atlbase.h"
#include "mapi.h"
#include "mapiutil.h"
LPTSTR strExchServerProfile = _T("TestExch");
#define
pbExchangeProviderPrimaryUserGuid "\x54\x94\xA1\xC0\x29\x7F\x10\x1B\xA5\x87\x08\x00\x2B\x2A\x25\x17"
//#define FIX_THE_PROBLEM
template <class T> class TidyMAPIBuffer
{
public:
TidyMAPIBuffer() {m_pb = NULL;}
virtual ~TidyMAPIBuffer() { Free(); }
T *operator&(){ return &m_pb; }
T operator->(){ return m_pb; }
operator T (){ return m_pb; }
void Attach(const T& t){ Free(); m_pb = t;}
T Detach() {T l; l = m_pb; m_pb = NULL; return l;}
virtual void Free() { if (m_pb) {MAPIFreeBuffer(m_pb); m_pb = NULL;} }
private:
TidyMAPIBuffer& operator=(const T &t); // No copy assignment operator!
TidyMAPIBuffer (const TidyMAPIBuffer& t); // No copy constructor!
protected:
T m_pb;
};
class TidyRowSet : public TidyMAPIBuffer<LPSRowSet>
{
public:
~TidyRowSet() { Free(); }
void Free() { if (m_pb) { FreeProws(m_pb); m_pb = NULL; }}
};
#define PR_PST_FILENAME PROP_TAG( PT_STRING8, 0x6700)
static char szService[] = "MSPST MS";
static char szUService[] = "MSUPST MS";
static char szPSTDisplayName[] = "PSTDisplayName";
//
////////////////////////////////////////////////////////////////////////////
// ExchangeLogon
//
////////////////////////////////////////////////////////////////////////////
HRESULT ExchangeLogon(IMAPISession **lppMAPISession)
{
HRESULT hr = S_OK;
try
{
// Logon to exchange using the profile in strExchServerProfile
if( SUCCEEDED( hr ) )
{
const FLAGS LogonFlags = MAPI_EXTENDED | MAPI_NT_SERVICE |
MAPI_EXPLICIT_PROFILE | MAPI_NEW_SESSION | MAPI_NO_MAIL;
hr = MAPILogonEx(0, strExchServerProfile, NULL, LogonFlags,
lppMAPISession);
if(FAILED(hr))
{
printf("ExchangeLogon: MAPILogonEx Failed 0x%.8x\n", hr);
}
}
}
catch(...)
{
printf("Exception in ExchangeLogon\n");
hr = E_FAIL;
}
return hr;
}
//
////////////////////////////////////////////////////////////////////////////
// OpenExchangeMailbox
//
////////////////////////////////////////////////////////////////////////////
HRESULT OpenExchangeMailbox(LPMAPISESSION lpMAPISession, LPMDB *lppUserMDB)
{
HRESULT hr = S_OK;
CComPtr<IMAPITable> lpMsgStoreTable;
TidyRowSet lpRows;
LPENTRYID lpMsgStoreID = NULL;
ULONG cbMsgStoreID = 0;
try
{
if(SUCCEEDED(hr))
{
// Get the list of message stores
hr = lpMAPISession->GetMsgStoresTable(0, &lpMsgStoreTable);
if(FAILED(hr))
{
printf("OpenExchangeMailbox: GetMsgStoresTable Failed 0x%.8x\n", hr);
}
}
if(SUCCEEDED(hr))
{
// Read all of the rows in the msg store table
hr = HrQueryAllRows(lpMsgStoreTable, NULL, NULL, NULL, 0, &lpRows);
if(FAILED(hr))
{
printf("OpenExchangeMailbox: HrQueryAllRows Failed 0x%.8x\n", hr);
}
}
if(SUCCEEDED(hr))
{
if (lpRows->cRows > 0)
{
for (UINT i=0; i < lpRows->cRows; i++)
{
LPSPropValue lpspv = PpropFindProp( lpRows->aRow[i].lpProps,
lpRows->aRow[i].cValues,
PR_MDB_PROVIDER );
if (lpspv)
{
if (memcmp(lpspv->Value.bin.lpb, pbExchangeProviderPrimaryUserGuid,
sizeof(GUID)) == 0)
{
lpspv = PpropFindProp( lpRows->aRow[i].lpProps,
lpRows->aRow[i].cValues,
PR_ENTRYID );
if (lpspv)
{
lpMsgStoreID = (LPENTRYID)lpspv->Value.bin.lpb;
cbMsgStoreID = lpspv->Value.bin.cb;
break;
}
}
}
}
}
}
if(SUCCEEDED(hr))
{
hr = lpMAPISession->OpenMsgStore(0, cbMsgStoreID, lpMsgStoreID, NULL,
MAPI_BEST_ACCESS, lppUserMDB);
if(FAILED(hr))
{
printf("OpenExchangeMailbox: OpenMsgStore Failed 0x%.8x\n", hr);
}
}
}
catch(...)
{
printf("Exception in OpenExchangeMailbox\n");
hr = E_FAIL;
}
return hr;
}
//
////////////////////////////////////////////////////////////////////////////
// TestCreatePST
//
////////////////////////////////////////////////////////////////////////////
HRESULT TestCreatePST(DWORD nPlace, BOOL bUnicode)
{
HRESULT hr = S_OK;
LPCSTR strType = (bUnicode) ? "Unicode" : "Ansi";
try
{
CComPtr<IMAPISession> pMAPIsession;
CComPtr<IProfAdmin> pProfAdmin;
CComPtr<IMsgServiceAdmin> pServiceAdmin;
CComPtr<IMAPITable> pServiceTable;
CComPtr<IMAPITable> pTblMsgStores;
CComPtr<IMsgStore> pMDB;
ULONG ulUI = NULL;
TidyRowSet pServiceTableRowset; // memory for PR_SERVICE_UID freed on
scope exit
LPMAPIUID pUIDService = NULL;
TidyRowSet pMsgStoresRowset; // memory for PR_ENTRYID freed on scope exit
LPSBinary pBinMsgStoreEID = NULL;
char szProfileName[64];
sprintf(szProfileName, "%s%d", bUnicode ? "U" : "A", nPlace);
char szPSTFileNameA[MAX_PATH + 50];
char path[MAX_PATH];
if( SUCCEEDED(hr) )
{
DWORD dw_gtp = 0;
dw_gtp = GetTempPathA(MAX_PATH, path);
if (dw_gtp == 0)
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
if (FAILED(hr))
{
printf("Place: %d: Type: %s: GetTempPathA Failed 0x%.8x\n", nPlace,
strType, hr);
}
}
if( SUCCEEDED(hr) )
{
sprintf(szPSTFileNameA, "%s%s%d.pst",path, bUnicode ? "U" : "A", nPlace);
::DeleteFileA(szPSTFileNameA);
}
if( SUCCEEDED(hr) )
{
hr = MAPIAdminProfiles( 0, &pProfAdmin );
if (FAILED(hr))
{
printf("Place: %d: Type: %s: MAPIAdminProfiles Failed 0x%.8x\n", nPlace,
strType, hr);
}
}
if( SUCCEEDED(hr) )
{
// Get rid of any existing profile
HRESULT hrDeleteProfile;
hrDeleteProfile = pProfAdmin->DeleteProfile((LPTSTR)szProfileName, 0);
if (FAILED(hrDeleteProfile))
{
//Ignore - the profile might not exist if the test has not been run before
//printf("Place: %d: Type: %s: DeleteProfile Failed 0x%.8x\n", nPlace,
strType, hrDeleteProfile);
}
}
if( SUCCEEDED(hr) )
{
// Setup a new Profile
hr = pProfAdmin->CreateProfile((LPTSTR)szProfileName, NULL, ulUI, 0 );
if (FAILED(hr))
{
printf("Place: %d: Type: %s: CreateProfile Failed 0x%.8x\n", nPlace,
strType, hr);
}
}
if( SUCCEEDED(hr) )
{
ULONG ulFlags = MAPI_EXTENDED | MAPI_NT_SERVICE | MAPI_EXPLICIT_PROFILE |
MAPI_NEW_SESSION | MAPI_NO_MAIL;
hr = MAPILogonEx( ulUI, (LPTSTR)szProfileName, NULL, ulFlags,
&pMAPIsession );
if (FAILED(hr))
{
printf("Place: %d: Type: %s: MAPILogonEx Failed 0x%.8x\n", nPlace,
strType, hr);
}
}
if( SUCCEEDED(hr) )
{
hr = pProfAdmin->AdminServices( (LPTSTR)szProfileName, NULL, ulUI, 0,
&pServiceAdmin );
if (FAILED(hr))
{
printf("Place: %d: Type: %s: pProfAdmin->AdminServices Failed 0x%.8x\n",
nPlace, strType, hr);
}
}
if( SUCCEEDED(hr) )
{
hr = pServiceAdmin->CreateMsgService( (bUnicode ? (LPTSTR)szUService :
(LPTSTR)szService),
(LPTSTR)szPSTDisplayName, 0, 0 );
if (FAILED(hr))
{
printf("Place: %d: Type: %s: CreateMsgService Failed 0x%.8x\n", nPlace,
strType, hr);
}
}
if( SUCCEEDED(hr) )
{
hr = pServiceAdmin->GetMsgServiceTable( 0, &pServiceTable );
if (FAILED(hr))
{
printf("Place: %d: Type: %s: GetMsgServiceTable Failed 0x%.8x\n",
nPlace, strType, hr);
}
}
if( SUCCEEDED(hr) )
{
SPropTagArray ptagaSvc = {1,{PR_SERVICE_UID}};
hr = HrQueryAllRows( pServiceTable, (LPSPropTagArray)&ptagaSvc, NULL,
NULL, 1, &pServiceTableRowset );
if (FAILED(hr))
{
printf("Place: %d: Type: %s: HrQueryAllRows(pServiceTable) Failed
0x%.8x\n", nPlace, strType, hr);
}
}
if( SUCCEEDED(hr) )
{
LPSRow prow = &pServiceTableRowset->aRow[0];
LPSPropValue pprop = prow->lpProps;
if ((pServiceTableRowset->cRows != 1) || (prow->cValues != 1))
{
hr = E_FAIL;
printf("Place: %d: Type: %s: HrQueryAllRows(pServiceTable) returned
unexpected row data\n", nPlace, strType);
}
else if (PROP_TYPE(pprop->ulPropTag) == PT_ERROR)
{
hr = pprop->Value.err;
printf("Place: %d: Type: %s: HrQueryAllRows(pServiceTable) returned
error property tag 0x%.8x\n", nPlace, strType, hr);
}
else
{
pUIDService = reinterpret_cast<LPMAPIUID>(pprop->Value.bin.lpb);
}
}
if( SUCCEEDED(hr) )
{
SPropValue pval;
pval.ulPropTag = PR_PST_FILENAME;
pval.dwAlignPad = 0;
pval.Value.lpszA = szPSTFileNameA;
hr = pServiceAdmin->ConfigureMsgService( pUIDService, NULL, 0, 1, &pval );
if (FAILED(hr))
{
printf("Place: %d: Type: %s: ConfigureMsgService Failed 0x%.8x\n",
nPlace, strType, hr);
}
}
#ifdef FIX_THE_PROBLEM
if( SUCCEEDED(hr) && bUnicode )
{
char strKeyName[512];
sprintf(strKeyName, "Software\\Microsoft\\Windows
NT\\CurrentVersion\\Windows Messaging
Subsystem\\Profiles\\%s\\9207f3e0a3b11019908b08002b2a56c2", szProfileName);
HKEY hk = NULL;
::RegOpenKeyA(HKEY_CURRENT_USER, strKeyName, &hk);
unsigned char buffer[512];
DWORD cbData = sizeof(buffer);
DWORD dwType = 0;
::RegQueryValueExA(hk, "01023d00", NULL, &dwType, &buffer[0], &cbData );
::RegCloseKey(hk);
sprintf(strKeyName, "Software\\Microsoft\\Windows
NT\\CurrentVersion\\Windows Messaging
Subsystem\\Profiles\\%s\\%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x",
szProfileName,
buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5],
buffer[6], buffer[7], buffer[8], buffer[9], buffer[10], buffer[11],
buffer[12], buffer[13], buffer[14], buffer[15]);
cbData = sizeof(buffer);
hk = NULL;
::RegOpenKeyA(HKEY_CURRENT_USER, strKeyName, &hk);
::RegSetValueExA(hk, "00036770", NULL, REG_BINARY,
(BYTE*)"\x00\x00\x00\x80", 4);
::RegCloseKey(hk);
}
#endif
if( SUCCEEDED(hr) )
{
hr = pMAPIsession->GetMsgStoresTable( 0, &pTblMsgStores );
if (FAILED(hr))
{
printf("Place: %d: Type: %s: GetMsgStoresTable Failed 0x%.8x\n", nPlace,
strType, hr);
}
}
if( SUCCEEDED(hr) )
{
SPropTagArray ptagaEid = {1,{PR_ENTRYID}};
hr = HrQueryAllRows( pTblMsgStores, &ptagaEid, NULL, NULL, 1,
&pMsgStoresRowset );
if (FAILED(hr))
{
printf("Place: %d: Type: %s: HrQueryAllRows(pTblMsgStores) Failed
0x%.8x\n", nPlace, strType, hr);
}
}
if( SUCCEEDED(hr) )
{
LPSRow prow = &pMsgStoresRowset->aRow[0];
LPSPropValue pprop = prow->lpProps;
if ((pMsgStoresRowset->cRows != 1) || (prow->cValues != 1))
{
hr = E_FAIL;
printf("Place: %d: Type: %s: HrQueryAllRows(pTblMsgStores) returned
unexpected row data\n", nPlace, strType);
}
else if (PROP_TYPE(pprop->ulPropTag) == PT_ERROR)
{
hr = pprop->Value.err;
printf("Place: %d: Type: %s: HrQueryAllRows(pTblMsgStores) returned
error property tag 0x%.8x\n", nPlace, strType, hr);
}
else
{
pBinMsgStoreEID = &pprop->Value.bin;
}
}
if( SUCCEEDED(hr) )
{
hr = pMAPIsession->OpenMsgStore( ulUI, pBinMsgStoreEID->cb,
(LPENTRYID)pBinMsgStoreEID->lpb, NULL, MAPI_BEST_ACCESS|MDB_NO_MAIL, &pMDB);
if (FAILED(hr))
{
printf("Place: %d: Type: %s: OpenMsgStore Failed 0x%.8x\n", nPlace,
strType, hr);
}
}
if( SUCCEEDED(hr) )
{
pMDB.Release();
pTblMsgStores.Release();
pServiceTable.Release();
pServiceAdmin.Release();
pProfAdmin.Release();
hr = pMAPIsession->Logoff(0,0,0);
pMAPIsession.Release();
if (FAILED(hr))
{
printf("Place: %d: Type: %s: Logoff Failed 0x%.8x\n", nPlace, strType,
hr);
}
}
if( SUCCEEDED(hr) )
{
printf("Place: %d: Type: %s: OK\n", nPlace, strType);
}
}
catch(...)
{
printf("Place: %d: Type: %s: Exception in TestCreatePST\n", nPlace,
strType);
hr = E_FAIL;
}
return hr;
}
//
////////////////////////////////////////////////////////////////////////////
// Test
//
////////////////////////////////////////////////////////////////////////////
void Test(BOOL bUnicode)
{
HRESULT hr = S_OK;
printf( "Testing %s PST Creation\n", (bUnicode) ? "Unicode" : "Ansi");
try
{
CComPtr<IMAPISession> lpMAPISession;
CComPtr<IMsgStore> lpMdb;
DWORD dwTestPlaceCount = 0;
// This test works in all cases
TestCreatePST(dwTestPlaceCount++, bUnicode);
if( SUCCEEDED(hr) )
{
hr = ExchangeLogon(&lpMAPISession);
if (FAILED(hr))
{
printf("ExchangeLogon Failed 0x%.8x\n", hr);
}
}
// This test works in all cases
TestCreatePST(dwTestPlaceCount++, bUnicode);
// Go open the Exchange mailbox for the first time
if( SUCCEEDED(hr) )
{
hr = OpenExchangeMailbox(lpMAPISession, &lpMdb);
if (FAILED(hr))
{
printf("OpenExchangeMailbox Failed 0x%.8x\n", hr);
}
}
if ( lpMdb == NULL )
{
printf("THIS TEST RUN IS INVALID. To exhibit the problem the exchange
mailbox must be sucessfully opened\n");
}
// This test only works if it is trying to create an Ansi PST
// The failure case that is reproduced here (creating a Unicode PST) is
the same as we see
// in our product when we have an exchange mailbox open and are trying to
create a Unicode PST.
TestCreatePST(dwTestPlaceCount++, bUnicode);
// Now release the pointer to the exchange mailbox
lpMdb.Release();
// Again, this test works in all cases
TestCreatePST(dwTestPlaceCount++, bUnicode);
// Open the Exchange mailbox for the second time to show that the problem
comes back
if( SUCCEEDED(hr) )
{
hr = OpenExchangeMailbox(lpMAPISession, &lpMdb);
if (FAILED(hr))
{
printf("OpenExchangeMailbox Failed 0x%.8x\n", hr);
}
}
if ( lpMdb == NULL )
{
printf("THIS TEST RUN IS INVALID. To exhibit the problem the exchange
mailbox must be sucessfully opened\n");
}
// This test only works if it is trying to create an Ansi PST
// The failure case that is reproduced here (creating a Unicode PST) is
the same as we see
// in our product when we have an exchange mailbox open and are trying to
create a Unicode PST.
TestCreatePST(dwTestPlaceCount++, bUnicode);
// Now release the pointer to the exchange mailbox
lpMdb.Release();
// Again, this test works in all cases
TestCreatePST(dwTestPlaceCount++, bUnicode);
}
catch(...)
{
printf("Exception in Test\n");
}
}
//
////////////////////////////////////////////////////////////////////////////
// _tmain
//
////////////////////////////////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[])
{
HRESULT hr;
printf("Hit [Return] to start\n");
fgetc(stdin);
CoInitialize(NULL);
MAPIINIT_0 MAPIINIT= { MAPI_INIT_VERSION, MAPI_MULTITHREAD_NOTIFICATIONS |
MAPI_NT_SERVICE };
hr = MAPIInitialize (&MAPIINIT);
Test(FALSE); // Ansi PST creation
printf("\n");
Test(TRUE); // Unicode PST creation
MAPIUninitialize();
CoUninitialize();
printf("\nHit [Return] to exit\n");
fgetc(stdin);
return 0;
}
.
- Follow-Ups:
- Re: OpenMsgStore returning MAPI_E_UNCONFIGURED
- From: Rhett Gong [MSFT]
- Re: OpenMsgStore returning MAPI_E_UNCONFIGURED
- References:
- Re: OpenMsgStore returning MAPI_E_UNCONFIGURED
- From: Karl Woodrow
- Re: OpenMsgStore returning MAPI_E_UNCONFIGURED
- From: Stephen Griffin [MSFT]
- Re: OpenMsgStore returning MAPI_E_UNCONFIGURED
- From: Richard Glanville
- Re: OpenMsgStore returning MAPI_E_UNCONFIGURED
- From: Stephen Griffin [MSFT]
- Re: OpenMsgStore returning MAPI_E_UNCONFIGURED
- From: Richard Glanville
- Re: OpenMsgStore returning MAPI_E_UNCONFIGURED
- From: Stephen Griffin [MSFT]
- Re: OpenMsgStore returning MAPI_E_UNCONFIGURED
- Prev by Date: RE: Determine the language used in an old style ANSI PST
- Next by Date: Re: question about ConfigureMsgService on xp without sp2
- Previous by thread: Re: OpenMsgStore returning MAPI_E_UNCONFIGURED
- Next by thread: Re: OpenMsgStore returning MAPI_E_UNCONFIGURED
- Index(es):