NEWPST.CPP

// --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);
}