370 lines
11 KiB
C++
370 lines
11 KiB
C++
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Microsoft WMIOLE DB Provider
|
|
// (C) Copyright 1999 Microsoft Corporation. All Rights Reserved.
|
|
//
|
|
// ITransLocal.cpp
|
|
// ITransactionLocal interface Implementation
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "headers.h"
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Commits a transaction
|
|
//
|
|
// Returns one of the following values:
|
|
// S_OK Method Succeeded
|
|
// E_FAIL a provider specific error occured
|
|
// XACT_E_ABORTED Transaction was aborted before Commit
|
|
// DB_E_UNEXPECTED An unexpected error occured
|
|
// XACT_E_COMMIT_FAILED Transaction commit failed due to unknow reason. Txn Aborted
|
|
// XACT_E_CONNECTION_DOWN Connection to datasource down
|
|
// XACT_E_NOTRANSACTION transaction had already been implicitly or explicityly commited/aborted
|
|
// XACT_E_NOTSUPPORTED Invalid combination of commit flags was specified
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP CImpITransactionLocal::Commit (BOOL fRetaining,
|
|
DWORD grfTC,
|
|
DWORD grfRM)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CSetStructuredExceptionHandler seh;
|
|
|
|
TRY_BLOCK;
|
|
|
|
// Seriliaze the object
|
|
CAutoBlock cab(m_pCDBSession->GetCriticalSection());
|
|
|
|
// Clear Error information
|
|
g_pCError->ClearErrorInfo();
|
|
|
|
//==============================================
|
|
// check if transaction is already started
|
|
//==============================================
|
|
if(!m_pCDBSession->IsTransactionActive())
|
|
{
|
|
hr = XACT_E_NOTRANSACTION;
|
|
}
|
|
else
|
|
{
|
|
//===============================================================================================
|
|
// call this functin to Commit transactions
|
|
//===============================================================================================
|
|
if(SUCCEEDED(hr = m_pCDBSession->m_pCDataSource->m_pWbemWrap->CompleteTransaction(FALSE,0))) // put the commit function here
|
|
{
|
|
m_pCDBSession->SetTransactionActive(FALSE);
|
|
}
|
|
}
|
|
|
|
if(SUCCEEDED(hr) && fRetaining)
|
|
{
|
|
m_pCDBSession->SetAllOpenRowsetToZoombieState();
|
|
}
|
|
|
|
hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_ITransactionLocal);
|
|
|
|
CATCH_BLOCK_HRESULT(hr,L"ITransactionLocal::Commit");
|
|
return hr;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Aborts a transaction
|
|
//
|
|
// Returns one of the following values:
|
|
// S_OK Method Succeeded
|
|
// E_FAIL a provider specific error occured
|
|
// DB_E_UNEXPECTED An unexpected error occured
|
|
// XACT_E_CONNECTION_DOWN Connection to datasource down
|
|
// XACT_E_NOTRANSACTION transaction had already been implicitly or explicityly commited/aborted
|
|
// XACT_E_NOTSUPPORTED fAsync was TRUE on input and async abort operation not supported
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP CImpITransactionLocal::Abort (BOID *pboidReason,
|
|
BOOL fRetaining,
|
|
BOOL fAsync)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CSetStructuredExceptionHandler seh;
|
|
|
|
TRY_BLOCK;
|
|
|
|
// Seriliaze the object
|
|
CAutoBlock cab(m_pCDBSession->GetCriticalSection());
|
|
|
|
// Clear Error information
|
|
g_pCError->ClearErrorInfo();
|
|
|
|
if(fAsync)
|
|
{
|
|
hr = XACT_E_NOTSUPPORTED;
|
|
}
|
|
else
|
|
if(fRetaining)
|
|
{
|
|
hr = XACT_E_CANTRETAIN;
|
|
}
|
|
//==============================================
|
|
// check if transaction is already started
|
|
//==============================================
|
|
else
|
|
if(!m_pCDBSession->IsTransactionActive())
|
|
{
|
|
hr = XACT_E_NOTRANSACTION;
|
|
}
|
|
else
|
|
{
|
|
//===============================================================================================
|
|
// call this functin to Abort transactions
|
|
//===============================================================================================
|
|
if(SUCCEEDED(hr = m_pCDBSession->m_pCDataSource->m_pWbemWrap->CompleteTransaction(TRUE,0))) // put the commit function here
|
|
{
|
|
m_pCDBSession->SetTransactionActive(FALSE);
|
|
}
|
|
}
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
m_pCDBSession->SetAllOpenRowsetToZoombieState();
|
|
}
|
|
|
|
hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_ITransactionLocal);
|
|
|
|
CATCH_BLOCK_HRESULT(hr,L"ITransactionLocal::Abort");
|
|
return hr;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Get information regarding transaction
|
|
//
|
|
// Returns one of the following values:
|
|
// S_OK Method Succeeded
|
|
// E_FAIL a provider specific error occured
|
|
// DB_E_UNEXPECTED An unexpected error occured
|
|
// DB_E_INVALIDARG pInfo was a null pointer
|
|
// XACT_E_NOTRANSACTION Unable to retrieve info because txn was already completed
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP CImpITransactionLocal::GetTransactionInfo (XACTTRANSINFO *pinfo)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CSetStructuredExceptionHandler seh;
|
|
|
|
TRY_BLOCK;
|
|
|
|
// Seriliaze the object
|
|
CAutoBlock cab(m_pCDBSession->GetCriticalSection());
|
|
|
|
// Clear Error information
|
|
g_pCError->ClearErrorInfo();
|
|
|
|
if(pinfo == NULL)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
else
|
|
if(!m_pCDBSession->IsTransactionActive())
|
|
{
|
|
hr = XACT_E_NOTRANSACTION;
|
|
}
|
|
else
|
|
{
|
|
// XACTUOW uow;
|
|
// GetCurrentUOW(uow);
|
|
pinfo->uow = m_pCDBSession->GetCurrentUOW();
|
|
pinfo->isoLevel = m_pCDBSession->GetIsolationLevel();
|
|
pinfo->isoFlags = 0;
|
|
pinfo->grfTCSupported = XACTTC_SYNC;
|
|
pinfo->grfRMSupported = 0;
|
|
pinfo->grfTCSupportedRetaining = 0;
|
|
pinfo->grfRMSupportedRetaining = 0;
|
|
}
|
|
|
|
hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_ITransactionLocal);
|
|
|
|
CATCH_BLOCK_HRESULT(hr,L"ITransactionLocal::GetTransactionInfo");
|
|
return hr;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Get the options object for the transaction
|
|
// Returns an object which can be used to specify configuration options for subsequent
|
|
// call to ITransactionLocal::StartTransaction
|
|
//
|
|
// Returns one of the following values:
|
|
// S_OK Method Succeeded
|
|
// E_FAIL a provider specific error occured
|
|
// DB_E_UNEXPECTED An unexpected error occured
|
|
// DB_E_INVALIDARG ppObtions was a null pointer
|
|
// E_OUTOFMEMORY unable to allocate memory
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP CImpITransactionLocal::GetOptionsObject(ITransactionOptions ** ppOptions)
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
CSetStructuredExceptionHandler seh;
|
|
|
|
TRY_BLOCK;
|
|
|
|
// Seriliaze the object
|
|
CAutoBlock cab(m_pCDBSession->GetCriticalSection());
|
|
|
|
// Clear Error information
|
|
g_pCError->ClearErrorInfo();
|
|
|
|
if(ppOptions)
|
|
{
|
|
*ppOptions = NULL;
|
|
CTranOptions *pNewOptions = NULL;
|
|
hr = E_OUTOFMEMORY;
|
|
try
|
|
{
|
|
pNewOptions = new CTranOptions;
|
|
}
|
|
catch(...)
|
|
{
|
|
SAFE_DELETE_PTR(pNewOptions);
|
|
throw;
|
|
}
|
|
|
|
if(pNewOptions)
|
|
{
|
|
hr = S_OK;
|
|
if(SUCCEEDED(hr = pNewOptions->FInit()))
|
|
{
|
|
hr = pNewOptions->QueryInterface(IID_ITransactionOptions , (void **)ppOptions);
|
|
}
|
|
else
|
|
{
|
|
SAFE_DELETE_PTR(pNewOptions);
|
|
}
|
|
}
|
|
}
|
|
|
|
hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_ITransactionLocal);
|
|
|
|
CATCH_BLOCK_HRESULT(hr,L"ITransactionLocal::GetOptionsObject");
|
|
return hr;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Begins a new transaction
|
|
//
|
|
// Returns one of the following values:
|
|
// S_OK Method Succeeded
|
|
// E_FAIL a provider specific error occured
|
|
// DB_E_OBJECTOPEN a rowset object was open and provider does not support starting a
|
|
// new transaction with an existing open rowset/row object open
|
|
// DB_E_UNEXPECTED An unexpected error occured
|
|
// XACT_E_CONNECTIONDENIED session could not create a new transaction at the present time
|
|
// XACT_E_CONNECTION_DOWN Session is having communication difficulties
|
|
// XACT_E_NOISORETAIN Requested semantics of retention of isolation across retaining
|
|
// commit/abort boundaries cannot be supported or isoFlags was
|
|
// not equal to zero
|
|
// XACT_E_XTIONEXISTS Session can handle only one extant transaction ata time and
|
|
// there is presently such a transaction.
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP CImpITransactionLocal::StartTransaction( ISOLEVEL isoLevel,
|
|
ULONG isoFlags,
|
|
ITransactionOptions *pOtherOptions,
|
|
ULONG *pulTransactionLevel)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CSetStructuredExceptionHandler seh;
|
|
LONG lFlags = 0;
|
|
|
|
TRY_BLOCK;
|
|
|
|
// Seriliaze the object
|
|
CAutoBlock cab(m_pCDBSession->GetCriticalSection());
|
|
|
|
// Clear Error information
|
|
g_pCError->ClearErrorInfo();
|
|
|
|
|
|
//==============================================
|
|
// check if transaction is already started
|
|
//==============================================
|
|
if(m_pCDBSession->IsTransactionActive())
|
|
{
|
|
hr = XACT_E_XTIONEXISTS;
|
|
}
|
|
else
|
|
{
|
|
XACTOPT xOpt;
|
|
GUID guidTrans;
|
|
// NTBug:111816
|
|
// 06/07/00
|
|
hr = CoCreateGuid(&guidTrans);
|
|
xOpt.ulTimeout = 0;
|
|
memset(xOpt.szDescription,0,MAX_TRAN_DESC * sizeof(unsigned char));
|
|
|
|
if(SUCCEEDED(hr) && pOtherOptions)
|
|
{
|
|
hr = pOtherOptions->GetOptions(&xOpt);
|
|
}
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
if(SUCCEEDED(hr = GetFlagsForIsolation(isoLevel,lFlags)))
|
|
{
|
|
//===============================================================================================
|
|
// call this functin to start a transaction
|
|
//===============================================================================================
|
|
if(SUCCEEDED(hr = m_pCDBSession->GenerateNewUOW(guidTrans)) &&
|
|
SUCCEEDED(hr = m_pCDBSession->m_pCDataSource->m_pWbemWrap->BeginTransaction(xOpt.ulTimeout,lFlags,&guidTrans))) // put the commit function here
|
|
{
|
|
m_pCDBSession->SetTransactionActive(TRUE);
|
|
m_pCDBSession->SetIsolationLevel(isoLevel);
|
|
if(pulTransactionLevel)
|
|
{
|
|
*pulTransactionLevel = 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_ITransactionLocal);
|
|
|
|
CATCH_BLOCK_HRESULT(hr,L"ITransactionLocal::StartTransaction");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CImpITransactionLocal::GetFlagsForIsolation(ISOLEVEL isoLevel,LONG &lFlag)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
lFlag = 0;
|
|
switch(isoLevel)
|
|
{
|
|
case ISOLATIONLEVEL_READCOMMITTED:
|
|
lFlag = 0;
|
|
break;
|
|
/*
|
|
case ISOLATIONLEVEL_CURSORSTABILITY:
|
|
case ISOLATIONLEVEL_REPEATABLEREAD:
|
|
//lFlags = Read
|
|
break;
|
|
|
|
case ISOLATIONLEVEL_SERIALIZABLE:
|
|
case ISOLATIONLEVEL_ISOLATED:
|
|
// lFlags = write
|
|
break;
|
|
*/
|
|
|
|
default:
|
|
hr = XACT_E_ISOLATIONLEVEL;
|
|
|
|
}
|
|
|
|
return hr;
|
|
} |