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