windows-nt/Source/XPSP1/NT/admin/wmi/wbem/adapters/oledb/dbsess.cpp

763 lines
25 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Microsoft WMIOLE DB Provider
// (C) Copyright 1999 Microsoft Corporation. All Rights Reserved.
//
//
// CDBSession object implementation
//
// NTRaid:: 139685 Transaction support removed
//////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "headers.h"
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Constructor for this class
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////
CDBSession::CDBSession( LPUNKNOWN pUnkOuter ) : CBaseObj(BOT_SESSION, pUnkOuter)
{
//==========================================================================
// Initialize simple member vars
//==========================================================================
m_nOpenedRowset = 0;
m_bTxnStarted = FALSE;
//==========================================================================
// Initially, NULL all contained interfaces
//==========================================================================
m_pIGetDataSource = NULL;
m_pIOpenRowset = NULL;
m_pISchemaRowset = NULL;
m_pIDBCreateCommand = NULL;
m_pISessionProperties = NULL;
m_pUtilProp = NULL;
m_pITableDefinition = NULL;
m_pISessionCache = NULL;
m_pIBindResource = NULL;
m_pIIndexDefinition = NULL;
m_pIAlterTable = NULL;
m_pISupportErrorInfo = NULL;
m_pITransLocal = NULL;
//==========================================================================
// Pointer to parent object
//==========================================================================
m_pCDataSource = NULL;
memset(&m_TxnGuid , 0 , sizeof(XACTUOW));
//==========================================================================
// Increment global object count.
//==========================================================================
InterlockedIncrement(&g_cObj);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Destructor for this class
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////
CDBSession:: ~CDBSession ( void )
{
//===========================================================================
// Free properties management object
//===========================================================================
SAFE_DELETE_PTR( m_pUtilProp );
//===========================================================================
// Free contained interfaces
//===========================================================================
SAFE_DELETE_PTR( m_pIGetDataSource );
SAFE_DELETE_PTR( m_pIOpenRowset );
SAFE_DELETE_PTR( m_pISchemaRowset );
SAFE_DELETE_PTR( m_pIDBCreateCommand );
SAFE_DELETE_PTR( m_pISessionProperties );
SAFE_DELETE_PTR( m_pITableDefinition );
SAFE_DELETE_PTR(m_pIBindResource);
SAFE_DELETE_PTR(m_pIIndexDefinition);
SAFE_DELETE_PTR(m_pIAlterTable);
SAFE_DELETE_PTR(m_pISupportErrorInfo);
// SAFE_DELETE_PTR(m_pITransLocal);
m_pCDataSource->RemoveSession();
m_pCDataSource->GetOuterUnknown()->Release();
//===========================================================================
// Decrement global object count.
//===========================================================================
InterlockedDecrement(&g_cObj);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Initialize the command Object
//
// Did the Initialization Succeed
// TRUE Initialization succeeded
// FALSE Initialization failed
//////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CDBSession::FInit ( CDataSource *pCDataSource )
{
HRESULT hr = E_OUTOFMEMORY;
//===========================================================================
// Establish parent object pointer
//===========================================================================
assert( pCDataSource );
m_pCDataSource = pCDataSource;
m_pCDataSource->GetOuterUnknown()->AddRef();
//===========================================================================
// Allocate properties management object
//===========================================================================
m_pUtilProp = new CUtilProp;
// NTRaid: 136443
// 07/05/00
if(m_pUtilProp == NULL)
{
hr = E_OUTOFMEMORY;
}
else
if(SUCCEEDED(hr = m_pUtilProp->FInit(SESSIONPROP)))
{
//===========================================================================
// Allocate contained interface objects
//===========================================================================
m_pIGetDataSource = new CImpIGetDataSource( this );
m_pIOpenRowset = new CImpIOpenRowset( this );
m_pISchemaRowset = new CImpIDBSchemaRowset( this );
m_pIDBCreateCommand = new CImpIDBCreateCommand( this );
m_pISessionProperties = new CImpISessionProperties( this );
m_pITableDefinition = new CImpITableDefinition( this );
m_pIBindResource = new CImplIBindRsrc( this );
m_pIIndexDefinition = new CImplIIndexDefinition( this );
m_pIAlterTable = new CImplIAlterTable( this );
m_pISupportErrorInfo = new CImpISupportErrorInfo(this);
// Removing transaction support as per alanbos mail ( core is removing the support)
// 06/30/2000
// m_pITransLocal = new CImpITransactionLocal(this);
if( m_pIGetDataSource && m_pIOpenRowset && m_pIDBCreateCommand && m_pISchemaRowset && m_pISessionProperties &&
m_pITableDefinition && m_pIBindResource && m_pIIndexDefinition && m_pIAlterTable) // && m_pITransLocal)
{
hr = S_OK;
}
else
{
hr = E_OUTOFMEMORY;
}
}
if(SUCCEEDED(hr))
{
hr = AddInterfacesForISupportErrorInfo();
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
// Function to add interfaces to ISupportErrorInfo interface
/////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CDBSession::AddInterfacesForISupportErrorInfo()
{
HRESULT hr = S_OK;
if( SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_IGetDataSource)) &&
SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_IOpenRowset)) &&
SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_IDBSchemaRowset)) &&
SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_ISessionProperties)) &&
SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_ITableDefinition)) &&
SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_IBindResource)) &&
SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_IDBCreateCommand)) &&
SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_IIndexDefinition)) &&
SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_ITransactionLocal)))
{
hr = m_pISupportErrorInfo->AddInterfaceID(IID_IAlterTable);
}
return hr;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Returns a pointer to a specified interface. Callers use QueryInterface to determine which interfaces
// the called object supports.
//
// HRESULT indicating the status of the method
// S_OK Interface is supported and ppvObject is set.
// E_NOINTERFACE Interface is not supported by the object
// E_INVALIDARG One or more arguments are invalid.
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CDBSession::QueryInterface ( REFIID riid, // IN | Interface ID of the interface being queried for.
LPVOID * ppv ) // OUT | Pointer to interface that was instantiated
{
HRESULT hr = E_INVALIDARG;
if(CheckIfValidDataSrc() == FALSE)
return g_pCError->PostHResult(hr,&IID_IUnknown);
//============================================================================
// Is the pointer bad?
//============================================================================
if (ppv != NULL){
//========================================================================
// Place NULL in *ppv in case of failure
//========================================================================
*ppv = NULL;
//========================================================================
// This is the non-delegating IUnknown implementation
//========================================================================
if (riid == IID_IUnknown)
*ppv = (LPVOID) this;
else if (riid == IID_IGetDataSource)
*ppv = (LPVOID) m_pIGetDataSource;
else if (riid == IID_IOpenRowset)
*ppv = (LPVOID) m_pIOpenRowset;
else if (riid == IID_IDBSchemaRowset)
*ppv = (LPVOID) m_pISchemaRowset;
else if (riid == IID_ISessionProperties)
*ppv = (LPVOID) m_pISessionProperties;
else if (riid == IID_ITableDefinition)
*ppv = (LPVOID) m_pITableDefinition;
else if (riid == IID_IBindResource)
*ppv = (LPVOID) m_pIBindResource;
else if ( riid == IID_IDBCreateCommand )
*ppv = (LPVOID)m_pIDBCreateCommand;
else if ( riid == IID_IIndexDefinition)
*ppv = (LPVOID)m_pIIndexDefinition;
else if ( riid == IID_IAlterTable)
*ppv = (LPVOID)m_pIAlterTable;
// Removing transaction support as per alanbos mail ( core is removing the support)
// 06/30/2000
// else if ( riid == IID_ITransactionLocal || riid == IID_ITransaction)
// *ppv = (LPVOID)m_pITransLocal;
else if ( riid == IID_ISupportErrorInfo)
*ppv = (LPVOID)m_pISupportErrorInfo;
//========================================================================
// If we're going to return an interface, AddRef it first
//========================================================================
if (*ppv){
((LPUNKNOWN) *ppv)->AddRef();
hr = S_OK;
}
else{
hr = E_NOINTERFACE;
}
}
return hr;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Increments a persistence count for the object
//
// Current reference count
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_( ULONG ) CDBSession::AddRef ( void )
{
return InterlockedIncrement((long *)&m_cRef);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Decrements a persistence count for the object and if persistence count is 0, the object destroys itself.
//
// Current reference count
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_( ULONG ) CDBSession::Release ( void )
{
if (!InterlockedDecrement((long *)&m_cRef)){
delete this;
return 0;
}
return m_cRef;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Gets a particular datasource property
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CDBSession::GetDataSrcProperty(DBPROPID propId , VARIANT & varValue)
{
return m_pCDataSource->GetDataSrcProperty(propId,varValue);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Creates a new command called by IBindResource implementation of the session
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CDBSession::CreateCommand(IUnknown *pUnkOuter, REFGUID riid,IUnknown ** ppCommand)
{
HRESULT hr = S_OK;
CCommand* pcmd = NULL;
if(CheckIfValidDataSrc() == FALSE)
{
hr = E_INVALIDARG;
}
else
{
//=========================================================================
// Initialize output param
//=========================================================================
if (ppCommand)
{
*ppCommand = NULL;
}
//=========================================================================
// Check Function Arguments
//=========================================================================
if( ppCommand == NULL )
{
hr = E_INVALIDARG;
}
else
//=========================================================================
// The outer object must explicitly ask for IUnknown
//=========================================================================
if (pUnkOuter != NULL && riid != IID_IUnknown)
{
hr = DB_E_NOAGGREGATION;
}
else
{
try
{
//=========================================================================
// This is the outer unknown from the user, for the new Command,
// not to be confused with the outer unknown of this DBSession object.
//=========================================================================
pcmd = new CCommand(this, pUnkOuter);
}
catch(...)
{
SAFE_DELETE_PTR(pcmd);
throw;
}
if (pcmd)
{
/* //=====================================================================
// Need to increment usage count since passed out to CCommand
//=====================================================================
m_pCDBSession->AddRef();
*/
//=====================================================================
// Initialize the command
//=====================================================================
hr = pcmd->FInit();
if( SUCCEEDED(hr) )
{
hr = pcmd->QueryInterface( riid, (void **) ppCommand );
if( SUCCEEDED(hr) )
{
// If everything is fine then set the datasource persist info to dirty
m_pCDataSource->SetPersistDirty();
}
//=================================================================
// Need to drop through on error, so command object is destroyed
//=================================================================
}
else
{
SAFE_DELETE_PTR(pcmd);
}
}
else
{
//=====================================================================
// Since Ctor failed, it cannot know to Release pUnkOuter,
// so we must do it here since we are owner.
//=====================================================================
if (pUnkOuter)
{
pUnkOuter->Release();
}
hr = E_OUTOFMEMORY;
}
} // else for NOAGGREGATION
} // else for INVALID_ARG
return hr;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Creates a new Row called by IBindResource implementation of the session
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CDBSession::CreateRow(IUnknown *pUnkOuter, WCHAR *pstrURL,REFGUID guidTemp,IUnknown ** ppUnk)
{
HRESULT hr = E_FAIL;
CRow * pNewRow = NULL;
DBPROPSET * pPropSet = NULL;
BSTR strTable;
BSTR strPath;
CURLParser urlParser;
strPath = Wmioledb_SysAllocString(pstrURL);
// Modified on 06/09/00
// Bug while getting a row from ADO Row object
// urlParser.SetPath(strPath);
urlParser.SetURL(strPath);
SysFreeString(strPath);
if(CheckIfValidDataSrc() == FALSE)
{
hr = E_INVALIDARG;
}
else
{
//===================================
// Get the path of the object
//===================================
if(SUCCEEDED(hr = urlParser.GetPathWithEmbededInstInfo(strPath)))
{
//===================================
// Get the class name
//===================================
// NTRaid:134967
// 07/11/2000
if(SUCCEEDED(hr) && SUCCEEDED(hr = m_pCDataSource->GetConnectionInitProperties(&pPropSet)))
{
hr = GetClassName(&urlParser,pPropSet,strTable,m_pCDataSource->m_pWbemWrap);
//==========================================================================
// Free memory we allocated to get the namespace property above
//==========================================================================
CPropertyMemoryMgr::FreeDBPROPSET( 1, pPropSet);
}
try
{
pNewRow = new CRow(pUnkOuter,this);
}
catch(...)
{
SAFE_DELETE_PTR(pNewRow);
throw;
}
if(SUCCEEDED(hr) && SUCCEEDED(hr = pNewRow->InitRow(strPath,strTable)))
{
hr = pNewRow->QueryInterface(guidTemp,(void **)ppUnk);
}
//=====================================================
// Free the strings allocated by the URLParser class
//=====================================================
SysFreeString(strTable);
SysFreeString(strPath);
if(FAILED(hr))
{
SAFE_DELETE_PTR(pNewRow);
*ppUnk = NULL;
}
}
} // INVALIDARG
return hr;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Creates a new Rowset called by IBindResource implementation of the session
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CDBSession::CreateRowset(IUnknown *pUnkOuter, WCHAR *pstrURL, REFGUID guidTemp,IUnknown ** ppUnk)
{
HRESULT hr = E_FAIL;
ULONG cPropSets = 0;
DBPROPSET* prgPropertySets = NULL;
BSTR strTableName = NULL;
CURLParser urlParser;
DBPROPSET * pPropSet = NULL;
{
CBSTR strTemp;
strTemp.SetStr(pstrURL);
urlParser.SetURL(pstrURL);
}
if(CheckIfValidDataSrc() == FALSE)
{
hr =E_INVALIDARG;
}
else
{
DBPROPIDSET rgPropIDSet[1];
rgPropIDSet[0].cPropertyIDs = 0;
rgPropIDSet[0].guidPropertySet = DBPROPSET_ROWSET;
//===============================
// Get the properties
//===============================
if(SUCCEEDED(hr = m_pUtilProp->GetProperties(PROPSET_ROWSET,0,rgPropIDSet, &cPropSets,&prgPropertySets)))
{
//====================================================
// Get the class name and initialize the tableID
//====================================================
// NTRaid:134967
// 07/11/2000
if( SUCCEEDED(hr = m_pCDataSource->GetConnectionInitProperties(&pPropSet)) )
{
hr = GetClassName(&urlParser,pPropSet,strTableName,m_pCDataSource->m_pWbemWrap);
if (SUCCEEDED(hr))
{
DBID tableID;
memset(&tableID , 0 , sizeof(DBID));
tableID.eKind = DBKIND_NAME;
tableID.uName.pwszName = strTableName;
//===============================
// Open the rowset
//===============================
hr = m_pIOpenRowset->OpenRowset(pUnkOuter,&tableID,NULL,guidTemp,cPropSets,prgPropertySets,ppUnk);
SAFE_FREE_SYSSTRING(strTableName);
}
//==========================================================================
// Free memory we allocated to get the namespace property above
//==========================================================================
CPropertyMemoryMgr::FreeDBPROPSET( 1, pPropSet);
}
//==========================================================================
// Free memory we allocated to by GetProperties
//==========================================================================
m_pUtilProp->m_PropMemMgr.FreeDBPROPSET( cPropSets, prgPropertySets);
}
}
return hr;
}
BOOL CDBSession::CheckIfValidDataSrc()
{
if(m_pCDataSource != NULL && m_pCDataSource->m_fDSOInitialized == TRUE)
return TRUE;
return FALSE;
}
HRESULT CDBSession::GenerateNewUOW(GUID &guidTrans)
{
HRESULT hr = S_OK;
assert (sizeof(XACTUOW) == sizeof(GUID));
if(SUCCEEDED(hr = CoCreateGuid(&guidTrans)))
{
memcpy(&m_TxnGuid.rgb,&guidTrans,sizeof(GUID));
}
return hr;
}
void CDBSession::AddRowset(CBaseRowObj * pRowset)
{
m_nOpenedRowset++;
m_OpenedRowsets.Add(pRowset);
}
void CDBSession::RemoveRowset(CBaseRowObj * pRowset)
{
m_nOpenedRowset--;
for( int i = 0 ; i < m_OpenedRowsets.Size(); i++)
{
if(pRowset == (CBaseRowObj *) m_OpenedRowsets.GetAt(i))
{
m_OpenedRowsets.RemoveAt(i);
break;
}
}
m_OpenedRowsets.Add(pRowset);
}
void CDBSession::SetAllOpenRowsetToZoombieState()
{
CBaseRowObj * pRowObj = NULL;
m_nOpenedRowset--;
for( int i = 0 ; i < m_OpenedRowsets.Size(); i++)
{
pRowObj = (CBaseRowObj *) m_OpenedRowsets.GetAt(i);
if(pRowObj != NULL)
{
pRowObj->SetStatusToZoombie();
}
pRowObj = NULL;
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Retrieve an interface pointer on the session object
//
//
// S_OK Session Object Interface returned
// E_INVALIDARG ppDataSource was NULL
// E_NOINTERFACE IID not supported
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CImpIGetDataSource::GetDataSource( REFIID riid, // IN IID desired
IUnknown** ppDataSource // OUT ptr to interface
)
{
HRESULT hr = E_INVALIDARG;
CSetStructuredExceptionHandler seh;
TRY_BLOCK;
// Seriliaze the object
CAutoBlock cab(m_pObj->GetCriticalSection());
// Clear ErrorInfo
g_pCError->ClearErrorInfo();
//========================================================================
// Check Function Arguments
//========================================================================
if( ppDataSource != NULL ){
assert(m_pObj->m_pCDataSource);
assert(m_pObj->m_pCDataSource->GetOuterUnknown());
//====================================================================
//Handle Aggregated DataSource (if aggregated)
//====================================================================
hr = m_pObj->m_pCDataSource->GetOuterUnknown()->QueryInterface(riid, (LPVOID*)ppDataSource);
}
hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_IGetDataSource);
CATCH_BLOCK_HRESULT(hr,L"IGetDataSource::GetDataSource");
return hr;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Returns current settings of all properties in the DBPROPFLAGS_SESSION property group
// HRESULT
// S_OK The method succeeded
// E_INVALIDARG pcProperties or prgPropertyInfo was NULL
// E_OUTOFMEMORY Out of memory
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CImpISessionProperties::GetProperties (
ULONG cPropertySets, // IN count of restiction guids
const DBPROPIDSET rgPropertySets[], // IN restriction guids
ULONG* pcProperties, // OUT count of properties returned
DBPROPSET** prgProperties // OUT property information returned
)
{
assert( m_pObj );
assert( m_pObj->m_pUtilProp );
HRESULT hr = S_OK;
CSetStructuredExceptionHandler seh;
TRY_BLOCK;
// Seriliaze the object
CAutoBlock cab(m_pObj->GetCriticalSection());
g_pCError->ClearErrorInfo();
//========================================================================
// Check Arguments
//========================================================================
hr = m_pObj->m_pUtilProp->GetPropertiesArgChk(PROPSET_SESSION, cPropertySets,
rgPropertySets, pcProperties, prgProperties);
if ( !FAILED(hr) ){
//========================================================================
// just pass this call on to the utility object that manages our
// properties
//========================================================================
hr = m_pObj->m_pUtilProp->GetProperties( PROPSET_SESSION,cPropertySets,rgPropertySets,pcProperties, prgProperties );
}
hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_ISessionProperties);
CATCH_BLOCK_HRESULT(hr,L"ISessionProperties::GetProperties ");
return hr;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Set properties in the DBPROPFLAGS_SESSION property group
//
// HRESULT
// E_INVALIDARG cProperties was not equal to 0 and rgProperties was NULL
// E_NOTIMPL this method is not implemented
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CImpISessionProperties::SetProperties ( ULONG cProperties, DBPROPSET rgProperties[] )
{
HRESULT hr = S_OK;
assert( m_pObj );
assert( m_pObj->m_pUtilProp );
CSetStructuredExceptionHandler seh;
TRY_BLOCK;
// Seriliaze the object
CAutoBlock cab(m_pObj->GetCriticalSection());
// Clear Error information
g_pCError->ClearErrorInfo();
//========================================================================
// Quick return if the Count of Properties is 0
//========================================================================
if( cProperties != 0 ){
//====================================================================
// Check Arguments for use by properties
//====================================================================
hr = m_pObj->m_pUtilProp->SetPropertiesArgChk(cProperties, rgProperties);
if( !FAILED(hr) ){
//====================================================================
// just pass this call on to the utility object that manages our properties
//====================================================================
hr = m_pObj->m_pUtilProp->SetProperties( PROPSET_SESSION,cProperties, rgProperties);
}
}
hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_ISessionProperties);
CATCH_BLOCK_HRESULT(hr,L"ISessionProperties::GetProperties ");
return hr;
}