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