home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 February / CHIP_2_98.iso / software / pelne / optionp / mts4.cab / Account.VC_CAccount.cpp < prev    next >
C/C++ Source or Header  |  1997-11-14  |  6KB  |  214 lines

  1. // Filename: CAccount.cpp
  2. //
  3. // Description: Implementation of CAccount
  4. //
  5. // This file is provided as part of the Microsoft Transaction Server
  6. // Software Development Kit
  7. //
  8. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT 
  9. // WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, 
  10. // INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES 
  11. // OF MERCHANTABILITY AND/OR FITNESS FOR A  PARTICULAR 
  12. // PURPOSE.
  13. //
  14. // Copyright (C) 1997 Microsoft Corporation, All rights reserved
  15. #include "stdafx.h"
  16. #include "Account.h"
  17. #include "CAccount.h"
  18. #include <stdio.h>
  19.  
  20. #include <mtx.h>
  21.  
  22. #include <adoid.h>
  23. #include <adoint.h>
  24.  
  25. /////////////////////////////////////////////////////////////////////////////
  26. //
  27.  
  28. STDMETHODIMP CAccount::InterfaceSupportsErrorInfo(REFIID riid)
  29. {
  30.     static const IID* arr[] = 
  31.     {
  32.         &IID_IAccount,
  33.     };
  34.     
  35.     for (int i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
  36.     {
  37.         if (InlineIsEqualGUID(*arr[i],riid))
  38.             return S_OK;
  39.     }
  40.     return S_FALSE;
  41. }
  42.  
  43. //    Post: modifies the specified account by the specified amount
  44. //
  45. //    pbstrResult: a BSTR giving information.  NOTE: this is set to NULL when an error occurs
  46. //
  47. //    returns:  S_OK or E_FAIL
  48.  
  49. STDMETHODIMP CAccount::Post (IN long lAccount, IN long lAmount, OUT BSTR* pbstrResult) {
  50.  
  51.     HRESULT hr = S_OK;
  52.  
  53.     IObjectContext* pObjectContext = NULL;
  54.  
  55.     ADOConnection* adoCoConnection = NULL;
  56.     ADORecordset* adoRsBalance = NULL;
  57.     ADOFields* pFields = NULL;
  58.     ADOField* pField = NULL;
  59.  
  60.     *pbstrResult = NULL;
  61.  
  62.     long lErrFlag = 0;
  63.     TCHAR* pErrMsg = NULL;
  64.  
  65.     try {
  66.  
  67.         // Get our object context
  68.         THROW_ERR (GetObjectContext(&pObjectContext), "GetObjectContext" );
  69.  
  70.         // Check security for large transfers
  71.         if (lAmount > 500 || lAmount < -500) {
  72.             BOOL bInRole;
  73.             BSTR bstrRole;
  74.         
  75.             bstrRole = ::SysAllocString(L"Managers");
  76.             hr = pObjectContext->IsCallerInRole (bstrRole, &bInRole);
  77.             ::SysFreeString(bstrRole);
  78.             
  79.             if (!SUCCEEDED ( hr )) {
  80.                 THROW_STR ( _T("IsCallerInRole() call failed!  Please add the 'Managers' Roll to the package."));
  81.             }
  82.             
  83.             if (!bInRole) {
  84.                 THROW_STR ( _T("Need 'Managers' role for amounts over $500") );
  85.             }
  86.         }
  87.  
  88.         // Create ADOConnection object and initialize the connection
  89.         THROW_ERR ( CoCreateInstance (CLSID_CADOConnection, NULL, CLSCTX_INPROC_SERVER, IID_IADOConnection,
  90.             (LPVOID *) &adoCoConnection), "CoCreateInstance(CADOConnection)" );
  91.  
  92.         BSTR bstrDSN = ::SysAllocString (L"FILEDSN=MTSSamples");
  93.         hr = adoCoConnection->Open (bstrDSN, NULL, NULL, adCmdUnspecified);
  94.         ::SysFreeString (bstrDSN);
  95.         RETHROW_ERR(hr);            
  96.  
  97.         // Update the account balance and
  98.         // then check to see if account would be overdrawn
  99.         TCHAR szBuffer [512];
  100.         wsprintf (szBuffer, _T("UPDATE Account SET Balance = Balance + %li WHERE AccountNo = %li"),
  101.             lAmount, lAccount);
  102.         BSTR bstrSQL = TCHAR2BSTR (szBuffer);
  103.         CComVariant vRecordCount;
  104.         vRecordCount.Clear();
  105.         hr = adoCoConnection->Execute(bstrSQL, &vRecordCount, -1, NULL);
  106.         ::SysFreeString (bstrSQL);
  107.         RETHROW_ERR(hr);            
  108.  
  109.         // If no records got updated, the account doesn't exist
  110.         if (vRecordCount.lVal == 0) {
  111.             TCHAR szBuffer1 [512];
  112.             wsprintf (szBuffer1, _T("Error. Account %ld not on file."), lAccount);        
  113.             THROW_STR ( szBuffer1 );
  114.         }
  115.  
  116.         wsprintf (szBuffer, _T("SELECT Balance FROM Account WHERE AccountNo = %ld"), lAccount);
  117.         bstrSQL = TCHAR2BSTR (szBuffer);
  118.         hr = adoCoConnection->Execute (bstrSQL, &vRecordCount, -1, &adoRsBalance);
  119.         ::SysFreeString (bstrSQL);
  120.         RETHROW_ERR(hr);            
  121.         // Get the appropriate fields
  122.         hr =  adoRsBalance->get_Fields(&pFields);
  123.         RETHROW_ERR(hr);
  124.  
  125.         // Get the appropriate field
  126.         CComVariant vField = L"Balance";
  127.         CComVariant vBalance;
  128.         hr = pFields->get_Item (vField, &pField) ;
  129.         RETHROW_ERR(hr);            
  130.         hr = pField->get_Value (&vBalance) ;
  131.         RETHROW_ERR(hr);
  132.  
  133.         // Check for overdraw, then prepare return string
  134.         if (vBalance.lVal < 0) {
  135.     
  136.             TCHAR szBuffer2 [512];
  137.             wsprintf (szBuffer2, _T("Error. Account %ld would be overdrawn by %ld.  Balance is still %ld"),
  138.                 lAccount, vBalance.lVal, vBalance.lVal - lAmount);        
  139.             THROW_STR ( szBuffer2 );
  140.         }
  141.         
  142.         TCHAR szBuffer3 [512];
  143.         wsprintf (szBuffer3, _T("%s account %ld, balance is $%ld. (VC++)"),
  144.             ((lAmount >= 0) ? _T("Credit to") : _T("Debit from")), lAccount, vBalance.lVal);
  145.         *pbstrResult = TCHAR2BSTR (szBuffer3);
  146.  
  147.         // Resource cleanup
  148.         if (pField) pField->Release();
  149.         if (pFields) pFields->Release();
  150.         if (adoRsBalance) adoRsBalance->Release();
  151.         if (adoCoConnection) adoCoConnection->Release();
  152.         
  153.         // We are finished and happy
  154.         pObjectContext->SetComplete();
  155.     
  156.         
  157.     } catch (HRESULT hr) {
  158.  
  159.         //
  160.         //    ErrorInfo is saved here because the following ADO cleanup code 
  161.         //    may clear it.
  162.         //
  163.         IErrorInfo * pErrorInfo = NULL;
  164.         GetErrorInfo(NULL, &pErrorInfo);
  165.  
  166.         if (pField)    pField->Release();
  167.         if (pFields) pFields->Release();
  168.         if (adoRsBalance) adoRsBalance->Release();
  169.         if (adoCoConnection) adoCoConnection->Release();
  170.  
  171.         // Fill in error information
  172.         switch (lErrFlag) {
  173.         
  174.         // Unknown error occurred in this object
  175.         case (0):
  176.             TCHAR szErr [512];
  177.             wsprintf (szErr, _T("Error 0x%x from CAccount calling %s."), hr, pErrMsg);
  178.             pErrMsg = szErr;
  179.             // Fall through
  180.         
  181.         // An application error occurred in this object
  182.         case (1):
  183.             //
  184.             //    we are going to put our own error in TLS, so if there is one there, clear it
  185.             //
  186.             if (pErrorInfo)
  187.                 pErrorInfo -> Release();
  188.             
  189.             AtlReportError( CLSID_CAccount, pErrMsg, IID_IAccount, hr);
  190.             break;
  191.         case (2): // ADO error
  192.         {
  193.             //
  194.             //    put the error back in TLS
  195.             //
  196.             SetErrorInfo(NULL, pErrorInfo);
  197.  
  198.         }
  199.         break;
  200.         // Will never reach here
  201.         default:            
  202.             break;
  203.         }
  204.         
  205.         // Indicate our unhappiness
  206.         if (pObjectContext)
  207.             pObjectContext->SetAbort();
  208.  
  209.     }
  210.  
  211.     if (pObjectContext)    pObjectContext->Release();
  212.  
  213.     return hr;
  214. }