// --newpst.cpp---------------------------------------------------------------
//
// Implementation of the newpst library
//
// Copyright (C) Microsoft Corp. 1986-1996. All rights reserved.
//
//-----------------------------------------------------------------------------
#include "edk.h"
#include "mspst.h"
#include "newpst.chk"
//
// Static storage
//
static BOOLfProfileCreated =FALSE;
static LPPROFADMINlpProfAdmin = NULL;
static LPSERVICEADMINlpSvcAdmin =NULL;
static MAPIUIDMsgStoreUID = {0};
//
// Functions
//
// $--HrCreatePersonalStore----------------------------------------------------------
//
// DESCRIPTION: Create a New PST with properties determined by the input
//parameters in a temporary profile. The name and password
//of the temporary PST are returned to the user.
//
// INPUT:
//
//[lpszPSTPath]-- Value for PR_PST_PATH (new PST path).
//[dwEncryption]-- Value for PR_PST_ENCRYPTION (TBS).
//[lpszPSTDisplayName]-- Value for PR_DISPLAY_NAME (new PST display name).
//[lpszPSTPassword]-- Value for PR_PST_PW_SZ_NEW (new PST password,
// NULL not accepted).
//
// OUTPUT:
//
//lppszProfileName-- Ptr that will be set to point at temporary
// profile name on return; this may be used to
// establish a MAPI session.
//lppszProfilePassword-- Ptr that will be set to point at temporary
// profile password on return; this may be used to
// establish a MAPI session.
//
// RETURNS: NOERROR on success,
// E_INVALIDARG if bad input,
// E_ACCESSDENIED if can access profile
// ` E_OUTOFMEMORY if memory problems
// E_FAIL on general failure.
//
// Notes:Successive calls to CreateNewPST() should not be made without
//intervening calls to NewPSTCleanup(). Due to use of internal
//static storage for objects and profile strings, only one new
//PST may be created and used at a time.
//
//---------------------------------------------------------------------------
HRESULT HrCreatePersonalStore( // RETURNS HRESULT
INLPSTRlpszPSTPath, // new PST fully-pathed name
INDWORDdwEncryption, // encryption level
INLPSTRlpszPSTDisplayName, // PR_DISPLAY_NAME value
INLPSTRlpszPSTPassword, // new PST password
OUTLPSTR *lppszProfileName, // temporary profile name
OUTLPSTR *lppszProfilePassword // temporary profile password
)
{
HRESULThr = NOERROR;
LPSPropValueaPropVals =NULL;
LPSRowSetlpRows =NULL;
LPMAPITABLElpTable =NULL;
const UINT cbProfile = 14; // # chars in temporary profile name
const UINT cbPassword = 1; // # char in temporary password
DEBUGPUBLIC("HrCreatePersonalStore()\n");
// Check input values
hr = CHK_HrCreatePersonalStore(lpszPSTPath, dwEncryption, lpszPSTDisplayName,
lpszPSTPassword, lppszProfileName,
lppszProfilePassword);
if ( FAILED(hr) )
{
RETURN(hr);
}
// Make sure we have not previously called CreateNewPST() without
// an intervening NewPSTCleanup() call. When this occurs, we just
// return E_FAIL and do no cleanup, thus leaving the
// previous profile and PST in place.
if (lpProfAdmin != NULL)
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
// Get a profile administration object.
hr = MAPIAdminProfiles(0, &lpProfAdmin);
if (FAILED(hr))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
// Allocate memory for temporary profile and password.
// Create the temporary profile.
hr = MAPIAllocateBuffer(cbPassword * sizeof(CHAR), // one character password
(PVOID *) lppszProfilePassword); // pointer to string pointer
if ( FAILED(hr) )
{
hr = HR_LOG(E_OUTOFMEMORY);
goto cleanup;
}
hr = MAPIAllocateBuffer(cbProfile * sizeof(CHAR),
(PVOID *) lppszProfileName);
if ( FAILED(hr) )
{
hr = HR_LOG(E_OUTOFMEMORY);
goto cleanup;
}
ASSERTERROR(!IsBadWritePtr(lppszProfileName, sizeof(LPSTR)),
"Bad lppszProfileName");
ASSERTERROR(!IsBadWritePtr(lppszProfilePassword, sizeof(LPSTR)),
"Bad lppszProfilePassword");
{
inti;
**lppszProfilePassword = '\0'; // no password
for (i = 0; (i < 1000) && (!fProfileCreated); i++)
{
sprintf(*lppszProfileName, "PstLoadTmp%03.3u", i);
hr = lpProfAdmin->CreateProfile(*lppszProfileName,
*lppszProfilePassword,
0,
0);
switch (hr)
{
case MAPI_E_NO_ACCESS: // name collision
hr = HR_LOG(E_ACCESSDENIED);
break;
default:
if ( FAILED(hr) )
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
fProfileCreated = TRUE;
} // end switch
} // end for
if (i == 1000)
{
goto cleanup;// MAPI_E_NO_ACCESS will be returned.
}
}
// Get a service administration object.
hr = lpProfAdmin->AdminServices(*lppszProfileName,
*lppszProfilePassword,
0,
0,
&lpSvcAdmin);
if (FAILED(hr))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
// Add the MS Personal Information Store service to the temporary profile.
// This will also happen to be set as the default store.
hr = lpSvcAdmin->CreateMsgService("MSPST MS",
"", // UI not used, so not needed.
0,
0);
if (FAILED(hr))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
// Configure the MS Personal Information Store per NewPST entries.
{
ULONGcValues = 0;
LPSPropValuelpProp = NULL;
hr = lpSvcAdmin->GetMsgServiceTable(0, &lpTable);
if (FAILED(hr))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
// We don't need to worry about checking all the columns; there should
// only be one since we just created the profile and added one service.
hr = lpTable->QueryRows(1, 0, &lpRows);
if (FAILED(hr))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
if (lpRows == NULL)
{
hr = HR_LOG(E_FAIL);// highly unlikely.
goto cleanup;
}
cValues =lpRows->aRow[0].cValues;
lpProp =lpRows->aRow[0].lpProps;
while (cValues)
{
if (lpProp->ulPropTag == PR_SERVICE_UID)
{
MsgStoreUID = *((LPMAPIUID)lpProp->Value.bin.lpb);
break;
}
lpProp++;
cValues--;
}
if (cValues == 0)
{
hr = HR_LOG(E_FAIL);// highly unlikely.
goto cleanup;
}
cValues = 6;
hr = MAPIAllocateBuffer(cValues * sizeof(SPropValue),
(LPVOID *)&aPropVals);
if ( FAILED(hr) )
{
hr = HR_LOG(E_OUTOFMEMORY);
goto cleanup;
}
aPropVals[0].ulPropTag =PR_DISPLAY_NAME;
aPropVals[0].Value.lpszA =lpszPSTDisplayName;
aPropVals[1].ulPropTag =PR_PST_PATH;
aPropVals[1].Value.lpszA =lpszPSTPath;;
aPropVals[2].ulPropTag =PR_PST_REMEMBER_PW;
aPropVals[2].Value.b =TRUE;
aPropVals[3].ulPropTag =PR_PST_ENCRYPTION;
aPropVals[3].Value.l =dwEncryption;
aPropVals[4].ulPropTag =PR_PST_PW_SZ_NEW;
aPropVals[4].Value.lpszA =lpszPSTPassword;
aPropVals[5].ulPropTag =PR_PST_PW_SZ_OLD;
aPropVals[5].Value.lpszA =*lppszProfilePassword;
hr = lpSvcAdmin->ConfigureMsgService(&MsgStoreUID,
0,
0,
cValues,
aPropVals);
if (FAILED(hr))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
}
cleanup:
FREEPROWS(lpRows);
ULRELEASE(lpTable);
MAPIFREEBUFFER(aPropVals);
// This makes it an "all or none" call.
if ( FAILED(hr) )
{
if ( lppszProfileName )
{
// remove temporary profile and
// release administration service.
HrCleanupPSTGlobals(*lppszProfileName);
MAPIFREEBUFFER(*lppszProfileName);
}
if ( lppszProfilePassword )
{
MAPIFREEBUFFER(*lppszProfilePassword);
}
} // end if failure
RETURN(hr);
}
// $--HrCleanupPSTGlobals-----------------------------------------------------------
//
// DESCRIPTION: Release objects involved in creation of a new PST.
//
// INPUT: temporary profile name
//
// RETURNS: NOERROR on success,
// E_FAIL if error.
//
// Notes:This should be called after Logoff() and Release() are called
//for the LPSESSION and before MAPIUninitialize() is called.
//---------------------------------------------------------------------------
HRESULT HrCleanupPSTGlobals( // RETURNS: HRESULT
IN LPSTR lpszProfileName) // temporary profile name
{
HRESULThr = NOERROR; // return code
DEBUGPUBLIC("HrCleanupPSTGlobals()\n");
// check input parameters
hr = CHK_HrCleanupPSTGlobals(lpszProfileName);
if ( FAILED(hr) )
{
RETURN(hr);
}
ULRELEASE(lpSvcAdmin);
if (fProfileCreated)
{
hr = lpProfAdmin->DeleteProfile(lpszProfileName, 0);
}
ULRELEASE(lpProfAdmin);
lpSvcAdmin =NULL;
fProfileCreated =FALSE;
lpProfAdmin =NULL;
RETURN(hr);
}