MOVEMONEY.CPP
// Filename: MoveMoney.cpp 
// 
// Description: Implementation of CMoveMoney 
// 
// This file is provided as part of the Microsoft Transaction Server 
// Software Development Kit 
// 
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT  
// WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,  
// INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES  
// OF MERCHANTABILITY AND/OR FITNESS FOR A  PARTICULAR  
// PURPOSE. 
// 
// Copyright (C) 1997 Microsoft Corporation, All rights reserved 
 
#include "stdafx.h" 
#include "Account.h" 
#include "MoveMoney.h" 
#include "Account.h" 
#include "GetReceipt.h" 
 
#include <mtx.h> 
#include <comdef.h> 
 
///////////////////////////////////////////////////////////////////////////// 
// 
 
STDMETHODIMP CMoveMoney::InterfaceSupportsErrorInfo(REFIID riid) 
{ 
static const IID* arr[] =  
{ 
&IID_IMoveMoney, 
}; 
 
for (int i=0;i<sizeof(arr)/sizeof(arr[0]);i++) 
{ 
if (InlineIsEqualGUID(*arr[i],riid)) 
return S_OK; 
} 
return S_FALSE; 
} 
 
//Perform: modifies the specified account by the specified amount 
// 
//pvResult: a BSTR giving information.  NOTE: this is set to NULL when an error occurs 
// 
//returns:  S_OK or E_FAIL 
 
STDMETHODIMP CMoveMoney::Perform (IN long lPrimeAccount, IN long lSecondAccount, IN long lAmount,  
  IN long lTranType, OUT BSTR* pbstrResult) { 
USES_CONVERSION; 
 
HRESULT hr = S_OK; 
 
IObjectContext* pObjectContext = NULL; 
 
IAccount* pObjAccount = NULL; 
IGetReceipt* pObjGetReceipt = NULL; 
 
long lErrFlag = 0; 
TCHAR* pErrMsg = NULL; 
 
BSTR bstrResult2 = NULL; 
BSTR bstrCall1 = NULL; 
BSTR bstrCall2 = NULL; 
 
*pbstrResult = NULL; 
 
try { 
 
// Get the object context 
THROW_ERR ( GetObjectContext (&pObjectContext), "GetObjectContext" ); 
 
// Check security for large transfers 
if (lAmount > 500 || lAmount < -500) { 
 
BOOL bInRole; 
BSTR bstrRole = ::SysAllocString (L"Managers"); 
hr = pObjectContext->IsCallerInRole (bstrRole, &bInRole); 
::SysFreeString(bstrRole); 
 
if (!SUCCEEDED ( hr )) { 
 
THROW_STR ( _T("IsCallerInRole() call failed!  Please add the 'Managers' Roll to the package.")); 
} 
 
if (!bInRole) { 
THROW_STR ( _T("Need 'Managers' role for amounts over $500") ); 
} 
} 
 
// Create the account object using our context 
THROW_ERR ( pObjectContext->CreateInstance(CLSID_CAccount, IID_IAccount, (void**)&pObjAccount), 
"CreateInstance(CLSID_CAccount)" ); 
 
// Call the post function based on the transaction type 
switch ( lTranType ) 
{ 
case (1):// debit 
RETHROW_ERR ( pObjAccount->Post (lPrimeAccount, 0 - lAmount, &bstrResult2) ); 
break; 
 
case (2):// credit 
RETHROW_ERR ( pObjAccount->Post (lPrimeAccount, lAmount, &bstrResult2) ); 
break; 
 
case (3):// transfer 
// Do the credit 
RETHROW_ERR ( pObjAccount->Post (lSecondAccount, lAmount, &bstrCall1) ); 
 
// Then do the debit 
RETHROW_ERR ( pObjAccount->Post (lPrimeAccount, 0 - lAmount, &bstrCall2) ); 
 
// Prepare return string 
TCHAR szBuf [512]; 
_tcscpy (szBuf, W2T( bstrCall1 )); 
_tcscat (szBuf, _T("; ")); 
_tcscat (szBuf, W2T( bstrCall2 )); 
bstrResult2 = TCHAR2BSTR (szBuf); 
break; 
 
default: 
THROW_STR ( _T("Invalid Transaction Type") ); 
} 
 
// Get Receipt Number for the transaction 
THROW_ERR ( pObjectContext->CreateInstance (CLSID_CGetReceipt, IID_IGetReceipt, (void**)&pObjGetReceipt), 
"CreateInstance(CLSID_CGetReceipt)" ); 
long lngReceiptNo; 
RETHROW_ERR ( pObjGetReceipt->GetNextReceipt(&lngReceiptNo) ); 
 
// Tag receipt information onto return string 
 
TCHAR szBuffer [512]; 
wsprintf (szBuffer, _T("; Receipt No:  %li"), lngReceiptNo); 
BSTR bstrTemp = TCHAR2BSTR (szBuffer); 
 
TCHAR szBuffer2 [512]; 
_tcscpy (szBuffer2, W2T ( bstrResult2 )); 
_tcscat (szBuffer2, W2T ( bstrTemp )); 
::SysFreeString (bstrTemp); 
 
*pbstrResult = TCHAR2BSTR (szBuffer2); 
 
 // We are finished and happy 
pObjectContext->SetComplete(); 
hr = S_OK; 
 
} catch (HRESULT hr) { 
 
// 
//store error info locally 
// 
 
IErrorInfo * pErrorInfo = NULL; 
GetErrorInfo(NULL, &pErrorInfo); 
 
// Fill in error information 
switch (lErrFlag) { 
 
// Unknown error occurred in this object 
case (0): 
TCHAR szErr [512]; 
wsprintf (szErr, _T("Error 0x%x from CMoveMoney calling %s."), hr, pErrMsg); 
pErrMsg = szErr; 
// Fall through 
 
// An application error occurred in this object 
case (1): 
// 
//we are going to put our own error in TLS, so if there is one there, clear it 
// 
if (pErrorInfo) 
pErrorInfo -> Release(); 
 
AtlReportError( CLSID_CMoveMoney, pErrMsg, IID_IMoveMoney, hr); 
break; 
 
case (2):// An error occurred in a called object 
// 
//put the error back in TLS 
// 
SetErrorInfo(NULL, pErrorInfo); 
break; 
 
// Will never reach here 
default: 
break; 
} 
 
 
// Indicate our unhappiness 
if (pObjectContext) 
pObjectContext->SetAbort(); 
} 
 
 
// Release resources 
if (pObjAccount) 
pObjAccount->Release(); 
 
if (pObjectContext) 
pObjectContext->Release(); 
 
if (pObjGetReceipt) 
pObjGetReceipt->Release(); 
 
if (bstrResult2) 
::SysFreeString (bstrResult2); 
 
if (bstrCall1) 
::SysFreeString (bstrCall1); 
 
if (bstrCall2) 
::SysFreeString (bstrCall2); 
 
return hr; 
}