Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

3124 lines
98 KiB

///////////////////////////////////////////////////////////////////////////////////
//
// Microsoft WMIOLE DB Provider
// (C) Copyright 1999 Microsoft Corporation. All Rights Reserved.
//
// CRowset object implementation
//
//
///////////////////////////////////////////////////////////////////////////////////
#include "headers.h"
#include "WmiOleDBMap.h"
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Constructor
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CRowset::CRowset(LPUNKNOWN pUnkOuter,PCDBSESSION pObj,CWbemConnectionWrapper *pCon ) : CBaseRowObj( pUnkOuter)
{
//===============================================================
// Initialize simple member vars
//===============================================================
InitVars();
m_pCreator = pObj;
m_pCreator->GetOuterUnknown()->AddRef();
//===============================================
// Add this rowset ot list of open rowset
//===============================================
m_pCreator->AddRowset(this);
m_pCon = pCon;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// Constructor for this class , Initializing recordset for Qualifiers
//
/////////////////////////////////////////////////////////////////////////////////////////////////
CRowset::CRowset(LPUNKNOWN pUnkOuter,ULONG uQType, LPWSTR PropertyName,PCDBSESSION pObj , CWmiOleDBMap *pMap) : CBaseRowObj(NULL)
{
//===============================================================
// Initialize simple member vars
//===============================================================
InitVars();
m_pCreator = pObj;
m_pCreator->GetOuterUnknown()->AddRef();
//===============================================
// Add this rowset ot list of open rowset
//===============================================
m_pCreator->AddRowset(this);
m_pMap = pMap;
m_pMap->AddRef();
//======================================================================
// set the flag which indicates that this Rowset is a child recordsets;
//======================================================================
m_bIsChildRs = TRUE;
// Initializing the Qualifier properties
m_uRsType = uQType;
if ( m_uRsType == PROPERTYQUALIFIER)
{
m_strPropertyName = Wmioledb_SysAllocString(PropertyName);
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Function to Initialize all the member variables
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void CRowset::InitVars()
{
m_cCols = m_cCols = m_cNestedCols = 0L;
//===============================================================
// set the flag which indicates that this Rowset is not a child rowset
//===============================================================
m_bIsChildRs = FALSE;
//===============================================================
// Intialize buffered row count + pointers to allocated memory
//===============================================================
m_cRows = 0;
m_cbRowSize = 0;
m_irowMin = 0;
m_ulRowRefCount = 0;
m_dwStatus = 0;
m_bHelperFunctionCreated= FALSE;
m_hLastChapterAllocated = 0;
m_ulProps = 0;
m_ulLastFetchedRow = 0;
m_hRow = 0;
m_uRsType = 0;
m_cRef = 0L;
m_bIsChildRs = FALSE;
m_FetchDir = FETCHDIRNONE;
m_lLastFetchPos = 0;
m_lRowCount = -1;
m_hRowLastFetched = 0;
//===============================================================
// Initially, NULL all contained interfaces
//===============================================================
m_pIAccessor = (PIMPIACCESSOR)NULL;
m_pIColumnsInfo = NULL;
m_pIConvertType = NULL;
m_pIRowset = NULL;
m_pIRowsetChange = NULL;
m_pIRowsetIdentity = NULL;
m_pIRowsetInfo = NULL;
m_pIChapteredRowset = NULL;
m_pIGetRow = NULL;
m_pIRowsetRefresh = NULL;
m_pRowFetchObj = NULL;
m_ppChildRowsets = NULL;
m_pInstance = NULL;
m_pParentCmd = NULL;
m_pIBuffer = NULL;
m_pLastBindBase = NULL;
m_pRowData = NULL;
m_pUtilProp = NULL;
m_pChapterMgr = NULL;
m_pMap = NULL;
m_pCreator = NULL;
m_pHashTblBkmark = NULL;
m_InstMgr = NULL;
m_pISupportErrorInfo = NULL;
//===============================================================
// Increment global object count.
//===============================================================
InterlockedIncrement(&g_cObj);
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// Destructor for this class
/////////////////////////////////////////////////////////////////////////////////////////////////
CRowset::~CRowset( void )
{
//==============================================================
// Release all the open Rows
//==============================================================
ReleaseAllRows();
//================================================
// If Slot list is allocated, release them
//================================================
if (NULL != m_pIBuffer)
{
ReleaseSlotList( m_pIBuffer );
}
if ( m_uRsType == PROPERTYQUALIFIER)
{
SysFreeString(m_strPropertyName);
}
//===============================================================
// Free pointers.
//===============================================================
SAFE_DELETE_PTR( m_pUtilProp );
//===============================================================
// NOTE: m_pMap releases the class ptr in destructor
//===============================================================
m_pMap->Release();
SAFE_DELETE_PTR(m_pHashTblBkmark);
//===============================================================
// Free contained interfaces
//===============================================================
SAFE_DELETE_PTR( m_pIAccessor );
SAFE_DELETE_PTR( m_pIColumnsInfo );
SAFE_DELETE_PTR( m_pIConvertType );
SAFE_DELETE_PTR( m_pIRowset );
SAFE_DELETE_PTR( m_pIRowsetChange );
SAFE_DELETE_PTR( m_pIRowsetIdentity );
SAFE_DELETE_PTR( m_pIRowsetInfo );
SAFE_DELETE_PTR( m_pIChapteredRowset);
SAFE_DELETE_PTR( m_pIGetRow);
SAFE_DELETE_PTR( m_pIRowsetRefresh);
SAFE_DELETE_PTR(m_pISupportErrorInfo);
SAFE_DELETE_PTR(m_pRowData);
SAFE_DELETE_PTR(m_pRowFetchObj);
SAFE_DELETE_PTR(m_InstMgr);
//===============================================================
// Decrement the DBSession Count. GetSpecification is not
// possible anymore
//===============================================================
if( m_pCreator )
{
m_pCreator->GetOuterUnknown()->Release();
}
//===============================================================
// If rowset is created by command then, decrement the number of rowsets
// opened by the rowset and release the command pointer
//===============================================================
if(m_pParentCmd != NULL)
{
m_pParentCmd->DecrementOpenRowsets();
m_pParentCmd->GetOuterUnknown()->Release();
}
SAFE_DELETE_PTR(m_pChapterMgr);
//================================================
// Release child rowsets
//================================================
if(m_ppChildRowsets != NULL)
{
for(UINT nIndex = 0 ; nIndex < m_cTotalCols ; nIndex++)
{
if(m_ppChildRowsets[nIndex] != NULL)
{
m_ppChildRowsets[nIndex]->Release();
}
}
delete m_ppChildRowsets;
}
if(m_bNewConAllocated)
{
SAFE_DELETE_PTR(m_pCon);
}
//===============================================================
// Decrement global object count.
//===============================================================
InterlockedDecrement(&g_cObj);
}
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// Returns a pointer to a specified interface. Callers use QueryInterface to determine which
// interfaces the called object supports.
// Sucess of QI for some of the interfaces depend on some of the properties
//
// 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 CRowset::QueryInterface ( REFIID riid, LPVOID * ppv )
{
HRESULT hr = S_OK;
//======================================================
// Check parameters, if not valid return
//======================================================
if (NULL == ppv)
{
hr = E_INVALIDARG ;
}
else
{
//======================================================
// 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_IAccessor)
{
*ppv = (LPVOID) m_pIAccessor;
}
else if (riid == IID_IColumnsInfo)
{
*ppv = (LPVOID) m_pIColumnsInfo;
}
else if (riid == IID_IConvertType)
{
*ppv = (LPVOID) m_pIConvertType;
}
else if (riid == IID_IRowset)
{
*ppv = (LPVOID) m_pIRowset;
}
else if (riid == IID_IRowsetLocate && (m_ulProps & IROWSETLOCATE))
{
*ppv = (LPVOID) m_pIRowset;
}
else if (riid == IID_ISourcesRowset)
{
*ppv = (LPVOID) m_pIRowset;
}
else if (riid == IID_IRowsetChange && (m_ulProps & IROWSETCHANGE))
{
*ppv = (LPVOID) m_pIRowsetChange;
}
else if (riid == IID_IRowsetIdentity)
{
*ppv = (LPVOID) m_pIRowsetIdentity;
}
else if (riid == IID_IRowsetInfo)
{
*ppv = (LPVOID) m_pIRowsetInfo;
}
else if (riid == IID_IChapteredRowset && (m_ulProps & ICHAPTEREDROWSET))
{
*ppv = (LPVOID) m_pIChapteredRowset;
}
else if (riid == IID_IGetRow && (m_ulProps & IGETROW))
{
*ppv = (LPVOID) m_pIGetRow;
}
else if(riid == IID_IRowsetRefresh && (m_ulProps & IROWSETREFRESH))
{
*ppv = (LPVOID)m_pIRowsetRefresh;
}
else if(riid == IID_ISupportErrorInfo)
{
*ppv = (LPVOID)m_pISupportErrorInfo;
}
//======================================================
// If we're going to return an interface, AddRef first
//======================================================
if (*ppv)
{
((LPUNKNOWN) *ppv)->AddRef();
hr = S_OK ;
}
else
{
hr = E_NOINTERFACE;
}
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// Increments a persistence count for the object
//
// Returns Current reference count
//
/////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_( ULONG ) CRowset::AddRef( void )
{
return InterlockedIncrement((long*)&m_cRef);
}
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// Decrements a persistence count for the object and if persistence count is 0, the object
// destroys itself.
//
/////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_( ULONG ) CRowset::Release( void )
{
if (!InterlockedDecrement((long*)&m_cRef))
{
//===========================================================
// Mark the session as not having an open rowset anymore
//===========================================================
this->m_pCreator->RemoveRowset(this);
// this->m_pCreator->DecRowsetCount();
delete this;
return 0;
}
return m_cRef;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// Initialize the rowset for representing a row. This rowset will not be opened as a child rowset
// This is used when rowset is opened on a qualifier
//
//
// Did the Initialization Succeed
// S_OK Initialization succeeded
// E_INVALIDARG Some input data are incorrect
// E_OUTOFMEMORY Out of memory when allocate memory for member data
//
/////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRowset::InitRowsetForRow(LPUNKNOWN pUnkOuter ,
const ULONG cPropertySets,
const DBPROPSET rgPropertySets[] ,
CWbemClassWrapper *pInst)
{
HRESULT hr = S_OK;
HROW hRowCurrent = 0;
CBSTR strKey;
//================================================
// Initialize the member variables
//================================================
m_bIsChildRs = FALSE;
//==========================
// Inititialize the rowset
//==========================
if(S_OK == (hr =InitRowset(cPropertySets,rgPropertySets)))
{
m_pMap->GetInstanceKey(pInst,strKey);
m_pInstance = pInst;
//===========================================================================
// if there is atleast one row retrieved and there are neseted columns
// then allocate rows for the child recordsets
//===========================================================================
if(m_cNestedCols > 0 )
{
if(m_ppChildRowsets == NULL)
{
AllocateAndInitializeChildRowsets();
}
//=====================================================================
// Fill the HCHAPTERS for the column
//=====================================================================
if(S_OK != (hr = FillHChaptersForRow(pInst,strKey)))
{
hr = E_FAIL;
}
}
if( FAILED(hr = CreateHelperFunctions()))
{
return hr;
}
m_bHelperFunctionCreated = TRUE;
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// Overloaded Rowset Initialization function to initialize rowset created from a command object
//
// Did the Initialization Succeed
// S_OK Initialization succeeded
// E_INVALIDARG Some input data are incorrect
// E_OUTOFMEMORY Out of memory when allocate memory for member data
//
/////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRowset::InitRowset( const ULONG cPropertySets, const DBPROPSET rgPropertySets[],DWORD dwFlags, CQuery* p,PCCOMMAND pCmd )
{
HRESULT hr = S_OK;
//============================================
// Set the qualifier flags
//============================================
dwFlags = (long)dwFlags == -1 ? GetQualifierFlags() : dwFlags;
//==================================================================
// Create a CWmiOleDBMap class with the appropriate constructor
//==================================================================
m_pMap = new CWmiOleDBMap;
if( m_pMap != NULL)
{
if(SUCCEEDED(hr = m_pMap->FInit(dwFlags,p,m_pCon == NULL ?m_pCreator->m_pCDataSource->m_pWbemWrap: m_pCon)))
{
m_pMap->AddRef();
m_pParentCmd = pCmd;
m_uRsType = p->GetType(); // If it is a COMMAND_ROWSET or METHOD_ROWSET
//============================================
// To hold the parent command reference
//============================================
m_pParentCmd->GetOuterUnknown()->AddRef();
//=====================================================
// Call this function to do the rest of initialization
//=====================================================
hr = InitRowset(cPropertySets,rgPropertySets);
}
}
else
{
hr = E_OUTOFMEMORY;
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// Overloaded Rowset Initialization function
// This function is called for (1) Schema Rowsets via CSchema
//
// Did the Initialization Succeed
// S_OK Initialization succeeded
// E_INVALIDARG Some input data are incorrect
// E_OUTOFMEMORY Out of memory when allocate memory for member data
//
/////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRowset::InitRowset( int nBaseType,const ULONG cPropertySets, const DBPROPSET rgPropertySets[],LPWSTR TableID, DWORD dwFlags, LPWSTR SpecificTable )
{
HRESULT hr = S_OK;
//============================================
// Set the qualifier flags
//============================================
dwFlags = (long)dwFlags == -1 ? GetQualifierFlags() : dwFlags;
//==================================================================
// Create a CWmiOleDBMap class with the appropriate constructor
//==================================================================
m_pMap = new CWmiOleDBMap;
if( m_pMap != NULL)
{
if(SUCCEEDED(hr = m_pMap->FInit(nBaseType, dwFlags, TableID, SpecificTable,
m_pCon == NULL ?m_pCreator->m_pCDataSource->m_pWbemWrap: m_pCon)))
{
m_pMap->AddRef();
m_uRsType = SCHEMA_ROWSET;
//=====================================================
// Call this function to do the rest of initialization
//=====================================================
hr = InitRowset(cPropertySets,rgPropertySets);
}
}
else
{
hr = E_OUTOFMEMORY;
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// Overloaded Rowset Initialization function
// This function is called for (1) Schema Rowsets
// (2) rowsets created from IOpenrowset:OpenRowset
//
// Did the Initialization Succeed
// S_OK Initialization succeeded
// E_INVALIDARG Some input data are incorrect
// E_OUTOFMEMORY Out of memory when allocate memory for member data
//
/////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRowset::InitRowset( const ULONG cPropertySets, const DBPROPSET rgPropertySets[],LPWSTR TableID,BOOL fSchema , DWORD dwFlags )
{
HRESULT hr = S_OK;
VARIANT vValue;
VariantInit(&vValue);
//============================================
// Set the qualifier flags
//============================================
dwFlags = (long)dwFlags == -1 ? GetQualifierFlags() : dwFlags;
//==================================================================
// Create a CWmiOleDBMap class with the appropriate constructor
//==================================================================
m_pMap = new CWmiOleDBMap;
if( m_pMap != NULL)
{
if(wcscmp(TableID,OPENCOLLECTION) == 0)
{
INSTANCELISTTYPE instType = GetObjectTypeProp(cPropertySets,rgPropertySets);
hr = m_pMap->FInit(dwFlags,TableID,m_pCon == NULL ?m_pCreator->m_pCDataSource->m_pWbemWrap: m_pCon,instType);
}
else
{
hr = m_pMap->FInit(dwFlags,TableID,m_pCon == NULL ?m_pCreator->m_pCDataSource->m_pWbemWrap: m_pCon);
}
if(SUCCEEDED(hr))
{
m_pMap->AddRef();
m_uRsType = fSchema == TRUE ? SCHEMA_ROWSET : 0;
//=====================================================
// Call this function to do the rest of initialization
//=====================================================
hr = InitRowset(cPropertySets,rgPropertySets);
}
}
else
{
hr = E_OUTOFMEMORY;
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// Overloaded Rowset Initialization function
// This function is called for (1) ROwsets created for Scope/Container
//
// Did the Initialization Succeed
// S_OK Initialization succeeded
// E_INVALIDARG Some input data are incorrect
// E_OUTOFMEMORY Out of memory when allocate memory for member data
//
/////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRowset::InitRowset( const ULONG cPropertySets,
const DBPROPSET rgPropertySets[],
LPWSTR strObjectID,
LPWSTR strObjectToOpen,
INSTANCELISTTYPE objInstListType ,
DWORD dwFlags)
{
HRESULT hr = S_OK;
WCHAR *pstrTableID = NULL;
CWbemConnectionWrapper *pCon = m_pCon;
pstrTableID = strObjectID;
//============================================
// Set the qualifier flags
//============================================
dwFlags = (long)dwFlags == -1 ? GetQualifierFlags() : dwFlags;
if(!pstrTableID)
{
pstrTableID = new WCHAR[wcslen(OPENCOLLECTION) + 1];
if(pstrTableID)
{
wcscpy(pstrTableID,OPENCOLLECTION);
}
else
{
hr = E_OUTOFMEMORY;
}
}
if(SUCCEEDED(hr) && strObjectToOpen)
// wbem_wcsincmp(m_pCreator->m_pCDataSource->m_pWbemWrap->GetNamespace(),strObjectID,wcslen(m_pCreator->m_pCDataSource->m_pWbemWrap->GetNamespace())))
{
m_pCon = new CWbemConnectionWrapper;
if(m_pCon)
{
hr = m_pCon->FInit(pCon != NULL ? pCon : m_pCreator->m_pCDataSource->m_pWbemWrap,
strObjectToOpen,objInstListType);
m_bNewConAllocated = TRUE;
}
else
{
hr = E_OUTOFMEMORY;
}
}
if(SUCCEEDED(hr))
{
//==================================================================
// Create a CWmiOleDBMap class with the appropriate constructor
//==================================================================
m_pMap = new CWmiOleDBMap;
if( m_pMap != NULL)
{
if(SUCCEEDED(hr = m_pMap ->FInit(dwFlags,
pstrTableID,
m_pCon == NULL ?m_pCreator->m_pCDataSource->m_pWbemWrap: m_pCon,
objInstListType)))
{
m_pMap->AddRef();
//=====================================================
// Call this function to do the rest of initialization
//=====================================================
hr = InitRowset(cPropertySets,rgPropertySets);
}
}
else
{
hr = E_OUTOFMEMORY;
}
}
if(!strObjectID)
{
SAFE_DELETE_ARRAY(pstrTableID);
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// Initialize the rowset Object
//
// Did the Initialization Succeed
// S_OK Initialization succeeded
// E_INVALIDARG Some input data are incorrect
// E_OUTOFMEMORY Out of memory when allocate memory for member data
//
/////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRowset::InitRowset( const ULONG cPropertySets, const DBPROPSET rgPropertySets[] )
{
HRESULT hr = S_OK;
bool bRowChange = true;
ULONG cErrors = 0;
//============================================================================
// allocate utility object that manages our properties
//============================================================================
m_pUtilProp = new CUtilProp;
if ( m_pUtilProp == NULL )
{
hr = E_OUTOFMEMORY;
}
else
// NTRaid: 136443
// 07/05/00
if(SUCCEEDED(hr = m_pUtilProp->FInit(ROWSETPROP)))
{
//07/06/00
// NTRaid : 134987
if(m_uRsType == SCHEMA_ROWSET)
{
hr = InitializePropertiesForSchemaRowset();
}
else
if(m_uRsType == COMMAND_ROWSET )
{
hr = InitializePropertiesForCommandRowset();
}
else
if(m_uRsType == METHOD_ROWSET)
{
hr = InitializePropertiesForMethodRowset();
}
//============================================================================
// Set rowset properties
// May be setting of optional properties might have failed and so we can continue
//============================================================================
// hr = SetRowsetProperties(cPropertySets,rgPropertySets);
if(SUCCEEDED(hr) && SUCCEEDED(hr = SetRowsetProperties(cPropertySets,rgPropertySets)))
{
if(hr != S_OK)
{
cErrors++;
}
//===================================================================================
// Call this function to initialize some of the rowset properties, set some flags
// and set flags on CWmiOledbMap object
//===================================================================================
InitializeRowsetProperties();
//====================================================================
/// Get property and Set Serach Preferences
//====================================================================
hr = SetSearchPreferences();
//===================================================================================
// Get column the information for the rowset
//===================================================================================
if( S_OK == (hr = CBaseRowObj::GetColumnInfo()))
{
//=============================================================
// Initialize the first instance to zero if the rowset is
// not a child rowset
//=============================================================
if(m_bIsChildRs != TRUE && ( m_uRsType == 0 || m_uRsType == SCHEMA_ROWSET || m_uRsType == COMMAND_ROWSET || m_uRsType == METHOD_ROWSET))
{
hr = ResetInstances();
}
else
//======================================================================================
// Create the chaptermanager with CRowsetpointers only if the rowset is a child rowset
//======================================================================================
if(m_bIsChildRs == TRUE)
{
m_pChapterMgr = new CChapterMgr();
if ( !m_pChapterMgr )
{
hr = E_OUTOFMEMORY;
}
}
if(!FAILED(hr))
{
//=======================================================
// Call this function to allocate memory for all
// contained interfaces
//=======================================================
hr = AllocateInterfacePointers();
}
} // if( S_OK == (hr = CBaseRowObj::GetColumnInfo()))
} // if(!FAILED(hr)) after Setting the rowset properties
//===========================================================================
// Call this function to increment the number of rowsets opened by command
// if rowset is opened by command
//===========================================================================
if( SUCCEEDED(hr))
{
//==========================================================
// Call this function to initialize the ISupportErrorInfo;
//==========================================================
hr = AddInterfacesForISupportErrorInfo();
if(m_pParentCmd != NULL)
{
m_pParentCmd->IncrementOpenRowsets();
}
if(cErrors > 0)
{
hr = DB_S_ERRORSOCCURRED;
}
}
} // If Succeeded(hr) after allocating memory for utilprop
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////////////
// Allocate memory for the different interfaces
///////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRowset::AllocateInterfacePointers()
{
HRESULT hr = S_OK;
BOOL bRowChange = TRUE;
//===========================================================================================
// Allocate contained interface objects
// Note that our approach is simple - we always create *all* of the Rowset interfaces
// If our properties were read\write (i.e., could be set), we would need to
// consult properties to known which interfaces to create.
// Also, none of our interfaces conflict. If any did conflict, then we could
// not just blindly create them all.
//===========================================================================================
m_pIAccessor = new CImpIAccessor( this );
if( m_pIAccessor )
{
hr = m_pIAccessor->FInit() ;
}
else
hr = E_OUTOFMEMORY;
if(SUCCEEDED(hr))
{
m_pIColumnsInfo = new CImpIColumnsInfo( this );
m_pIConvertType = new CImpIConvertType(this);
m_pIRowset = new CImpIRowsetLocate( this );
if(m_ulProps & IROWSETCHANGE )
{
m_pIRowsetChange = new CImpIRowsetChange( this );
}
m_pIRowsetIdentity = new CImpIRowsetIdentity( this );
m_pIRowsetInfo = new CImpIRowsetInfo( this );
m_pIChapteredRowset = new CImpIChapteredRowset(this);
m_pIGetRow = new CImpIGetRow(this);
m_pIRowsetRefresh = new CImplIRowsetRefresh(this);
m_pISupportErrorInfo = new CImpISupportErrorInfo(this);
//===============================================================
// If rowset is pointing to qualifier then instantiate the
// qualifier fetch object
//===============================================================
if(m_uRsType == PROPERTYQUALIFIER || m_uRsType == CLASSQUALIFIER)
{
m_pRowFetchObj = (CRowFetchObj *)new CQualifierRowFetchObj;
}
else
{
m_pRowFetchObj = (CRowFetchObj *)new CInstanceRowFetchObj;
}
}
if(SUCCEEDED(hr))
{
if( (m_pIRowsetChange == NULL) && ((m_ulProps & IROWSETCHANGE) != 0))
{
bRowChange = FALSE;
}
//===========================================================================================
// if all interfaces were created, return success
//===========================================================================================
if( ! (m_pIAccessor && m_pIColumnsInfo && m_pIConvertType && m_pIRowset && bRowChange && m_pIRowsetIdentity && m_pIRowsetInfo && m_pIChapteredRowset && m_pIRowsetRefresh && m_pISupportErrorInfo))
{
hr = E_OUTOFMEMORY;
}
}
return hr;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////
// Function to initialize Rowset properties and also set some of the flags on CWMIOledbMap accordingly
//////////////////////////////////////////////////////////////////////////////////////////////////////////
void CRowset::InitializeRowsetProperties()
{
HRESULT hr = S_OK;
VARIANT varProp;
VariantInit(&varProp);
//===========================================================================================
// Initialize the common rowset properties ( boolean properties)
// and put that in the member variable
//===========================================================================================
GetCommonRowsetProperties();
//===========================================================================================
// set the forwardonly flag of enumerator to null depending on
// the properties
//===========================================================================================
// NTRaid 14199
// 07/14/2000. The navigation flags of the parent rowset for qualifier rowset was getting changed
if(!((CANSCROLLBACKWARDS & m_ulProps) || (CANFETCHBACKWARDS & m_ulProps) || (BOOKMARKPROP & m_ulProps)) ||
(m_uRsType == METHOD_ROWSET) && (m_uRsType != PROPERTYQUALIFIER || m_uRsType != CLASSQUALIFIER))
{
m_pMap->SetNavigationFlags(WBEM_FLAG_FORWARD_ONLY);
m_ulProps = m_ulProps & ~CANSCROLLBACKWARDS;
m_ulProps = m_ulProps & ~CANFETCHBACKWARDS;
m_ulProps = m_ulProps & ~BOOKMARKPROP;
m_ulProps = m_ulProps & ~IROWSETLOCATE;
}
//===========================================================================================
// If the custom WMIOLEDB property FETCHDEEP is set , then set the other OLEDB props
// which reflects the behaviour of the rowset
//===========================================================================================
if(FETCHDEEP & m_ulProps)
{
varProp.vt = VT_BOOL;
varProp.boolVal = VARIANT_TRUE;
m_pMap->SetQueryFlags(WBEM_FLAG_DEEP);
//===========================================================================================
// If enumeration is opened as FLAG_DEEP, it is bidirectional
// So set the respective properties
//===========================================================================================
SetRowsetProperty(DBPROP_CANSCROLLBACKWARDS,varProp);
SetRowsetProperty(DBPROP_CANFETCHBACKWARDS,varProp);
}
VariantClear(&varProp);
//===========================================================================================
// Get the DataSource property to check if system Properties is to be fetched?
//===========================================================================================
m_pCreator->GetDataSrcProperty(DBPROP_WMIOLEDB_SYSTEMPROPERTIES,varProp);
if( varProp.boolVal == VARIANT_TRUE)
{
m_pMap->SetSytemPropertiesFlag(TRUE);
}
VariantClear(&varProp);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
// Function to add interfaces to ISupportErrorInfo interface
/////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRowset::AddInterfacesForISupportErrorInfo()
{
HRESULT hr = S_OK;
if(SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_IAccessor)) &&
SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_IColumnsInfo)) &&
SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_IConvertType)) &&
SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_IRowset)) &&
SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_ISourcesRowset)) &&
SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_IRowsetIdentity)))
{
hr = m_pISupportErrorInfo->AddInterfaceID(IID_IRowsetInfo);
}
if(SUCCEEDED(hr) && (m_ulProps & IROWSETLOCATE))
{
hr = m_pISupportErrorInfo->AddInterfaceID(IID_IRowsetLocate);
}
if(SUCCEEDED(hr) && (m_ulProps & IROWSETCHANGE))
{
hr = m_pISupportErrorInfo->AddInterfaceID(IID_IRowsetChange);
}
if(SUCCEEDED(hr) && (m_ulProps & ICHAPTEREDROWSET))
{
hr = m_pISupportErrorInfo->AddInterfaceID(IID_IChapteredRowset);
}
if(SUCCEEDED(hr) && (m_ulProps & IGETROW))
{
hr = m_pISupportErrorInfo->AddInterfaceID(IID_IGetRow);
}
if(SUCCEEDED(hr) && (m_ulProps & IROWSETREFRESH))
{
hr = m_pISupportErrorInfo->AddInterfaceID(IID_IRowsetRefresh);
}
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Creates DBCOLINFO structures for each column in the result set.
//
// HRESULT
// S_OK Column Info Obtained
// E_FAIL Problems getting Column Info
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRowset::GatherColumnInfo()
{
//=======================================================
// Call GatherColumnInfo() on the base object
//=======================================================
HRESULT hr = CBaseRowObj::GatherColumnInfo();
//=============================================================
// Initialize the first instance to zero if the rowset is
// not a child rowset
//=============================================================
if(hr == S_OK && m_bIsChildRs != TRUE)
{
ResetInstances();
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// Creates Helper classes that are needed to manage the Rowset Object
//
// HRESULT
// S_OK Helper classes created
// E_FAIL Helper classes were not created
//
// NTRaid : 142133 & 141923
// 07/12/00
/////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRowset::CreateHelperFunctions ( void )
{
HRESULT hr = E_OUTOFMEMORY;
if(m_cTotalCols == 0)
{
hr = S_OK;
}
else
//============================================================================
// List of free slots.
// This manages the allocation of sets of contiguous rows.
//============================================================================
if (SUCCEEDED(hr = InitializeSlotList( MAX_TOTAL_ROWBUFF_SIZE / m_cbRowSize, m_cbRowSize, g_dwPageSize,
m_pIAccessor->GetBitArrayPtr(),&m_pIBuffer, &m_rgbRowData )))
{
//============================================================================
// Locate some free slots. Should be at very beginning.
// This tells us which row we will bind to: m_irowMin.
// After getting the slot just release it as this was just a test
//============================================================================
if (SUCCEEDED( hr = GetNextSlots( m_pIBuffer, 1, (HSLOT *)&m_irowMin )))
{
hr = ReleaseSlots( m_pIBuffer, m_irowMin, 1 );
}
}
if(SUCCEEDED(hr))
{
//=================================================
// Allocate and initialize rowdata manager
//=================================================
m_pRowData = new CRowDataMemMgr;
if( m_pRowData != NULL)
{
//=================================================
// Set the number of columns in row
//=================================================
m_pRowData->AllocRowData(m_cTotalCols);
hr = S_OK;
//=================================================
// Allocate memory for instance manager
//=================================================
m_InstMgr = new CWMIInstanceMgr;
if( m_InstMgr != NULL)
{
//==============================================================
// If bookmark is required then allocate an new hashtbl class
//==============================================================
if(m_ulProps & BOOKMARKPROP)
{
m_pHashTblBkmark = new CHashTbl;
if(m_pHashTblBkmark != NULL)
{
//=================================================
// Initialize the hashtable
//=================================================
m_pHashTblBkmark->FInit((PLSTSLOT)m_pIBuffer);
//=================================================
// Call this function to get the number of rows
//=================================================
GetRowCount();
hr = S_OK;
} // if(m_HashTblBkmark != NULL)
} // if( bookmark property is set)
} // if ( instance manage is allocated correctly)
else
{
hr = E_OUTOFMEMORY;
}
} // if( m_pRowData != NULL)
} // GetNextSlots succeeded
return hr ;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Establishes data offsets and type for the routines to place the data
//
// HRESULT
// S_OK Bindings set fine
// E_FAIL Bindings could not be set
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRowset::Rebind( BYTE *pBase ) // IN Base pointer for Data Area
{
HRESULT hr= 0;
UWORD icol;
COLUMNDATA *pColumn;
//==============================================================================
// Bind result set columns.
// Use established types and sizes and offsets.
// Bind to internal row buffer, area beginning with 'pRowBuff'.
//
// For each column, bind it's data as well as length.
// Offsets point to start of COLUMNDATA structure.
//==============================================================================
assert( pBase );
//==============================================================================
// Optimize by not doing it over again.
//==============================================================================
if (pBase != m_pLastBindBase)
{
hr = E_UNEXPECTED;
m_pLastBindBase = 0;
for (icol=0; icol < m_cTotalCols; icol++)
{
//======================================================================
// Parent columns... what about nested ?
//======================================================================
pColumn = (COLUMNDATA *) (pBase + m_Columns.GetDataOffset(icol));
hr = m_pRowData->SetColumnBind( icol, pColumn );
if( hr != S_OK )
{
break;
}
}
if( hr == S_OK )
{
//=================================================
// Remember in case we bind to same place again.
//=================================================
m_pLastBindBase = pBase;
}
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//
// Shorthand way to get the address of a row buffer. Later we may extend this so that it can span several
// non-contiguous blocks of memory.
//
// Pointer to the buffer.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
ROWBUFF* CRowset::GetRowBuff( HROW iRow, // IN Row to get address of.
BOOL fDataLocation ) // IN Get the Data offset.
{
HSLOT hSlot = -1;
//=====================================================================
// This assumes iRow is valid...
//=====================================================================
assert( m_rgbRowData );
assert( m_cbRowSize );
assert( iRow > 0 );
if(m_bIsChildRs == FALSE)
{
//=================================================
// Get the slot number for the row
//=================================================
hSlot = m_InstMgr->GetSlot(iRow);
}
//=================================================================================
// if rowset is refering to qualifiers then add the row to the particular chapter
//=================================================================================
else
{
//=================================================
// Get the slot number for the row
//=================================================
hSlot = m_pChapterMgr->GetSlot(iRow);
}
return (hSlot != -1) ? GetRowBuffer(m_pIBuffer,(ULONG)hSlot): NULL;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//
// Shorthand way to get the address of a row buffer.
//
// Pointer to the buffer.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
ROWBUFF* CRowset::GetRowBuffFromSlot( HSLOT hSlot, // IN Row to get address of.
BOOL fDataLocation ) // IN Get the Data offset.
{
//=====================================================================
// This assumes iRow is valid...
//=====================================================================
assert( m_rgbRowData );
assert( m_cbRowSize );
assert( hSlot >= 0 );
return GetRowBuffer(m_pIBuffer,hSlot);
}
////////////////////////////////////////////////////////////////////////////
// Reset the position of the instances in the enumerator to the begining
////////////////////////////////////////////////////////////////////////////
HRESULT CRowset::ResetInstances()
{
return m_pMap->ResetInstances();
}
////////////////////////////////////////////////////////////////////////////
// Reset the qualifer set of the property/class/instance
////////////////////////////////////////////////////////////////////////////
HRESULT CRowset::ResetQualifers(HCHAPTER hChapter)
{
HRESULT hr = S_OK;
CWbemClassWrapper *pInst = NULL;
//=====================================================================
// Get the pointer to instance for which qualifier is to
// be reset
//=====================================================================
if( hChapter > 0 && m_bIsChildRs == TRUE)
{
pInst = m_pChapterMgr->GetInstance(hChapter);
}
else
{
pInst = m_pInstance;
}
//=================================================
// If valid instance then reset the qualifier
//=================================================
if(pInst)
{
m_pMap->ReleaseQualifier(pInst,m_strPropertyName);
}
else
{
hr = DB_E_BADCHAPTER;
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////////
// Reset the position of the instances in the enumerator the required position
/////////////////////////////////////////////////////////////////////////////////
HRESULT CRowset::ResetRowsetToNewPosition(DBROWOFFSET uWhich,CWbemClassWrapper *pInst)
{
HRESULT hr = S_OK;
switch(m_uRsType)
{
case PROPERTYQUALIFIER:
hr = m_pMap->ResetPropQualiferToNewPosition(pInst,uWhich,m_strPropertyName);
break;
case CLASSQUALIFIER:
hr = m_pMap->ResetClassQualiferToNewPosition(pInst,uWhich);
break;
case SCHEMA_ROWSET:
// NTRaid : 134987
// 07/12/00
hr = m_pMap->ResetInstancesToNewPosition(uWhich);
break;
case 0:
case COMMAND_ROWSET:
case METHOD_ROWSET:
hr = m_pMap->ResetInstancesToNewPosition(uWhich);
break;
default:
hr = E_FAIL;
break;
}
return hr;
}
///////////////////////////////////////////////////////
// Get the pointer and key to the next instance
///////////////////////////////////////////////////////
HRESULT CRowset::GetNextInstance(CWbemClassWrapper *&ppInst,CBSTR &strKey, BOOL bFetchBack)
{
//=================================================
// Reset the column Index of the data manager
//=================================================
m_pRowData->ResetColumns();
return m_pMap->GetNextInstance(ppInst,strKey,bFetchBack);
}
///////////////////////////////////////////////////////
// Get the next property qualifier
///////////////////////////////////////////////////////
HRESULT CRowset::GetNextPropertyQualifier(CWbemClassWrapper *pInst,BSTR strPropName,BSTR &strQualifier,BOOL bFetchBack)
{
HRESULT hr = S_OK;
//=================================================
// Reset the column Index of the data manager
//=================================================
m_pRowData->ResetColumns();
hr = m_pMap->GetNextPropertyQualifier(pInst,strPropName,strQualifier,bFetchBack);
return hr;
}
///////////////////////////////////////////////////////
// Get the next Class qualifier
///////////////////////////////////////////////////////
HRESULT CRowset::GetNextClassQualifier(CWbemClassWrapper *pInst,BSTR &strQualifier,BOOL bFetchBack)
{
HRESULT hr = S_OK;
//=================================================
// Reset the column Index of the data manager
//=================================================
m_pRowData->ResetColumns();
hr = m_pMap->GetNextClassQualifier(pInst,strQualifier,bFetchBack);
return hr;
}
//////////////////////////////////////////////////////////////////////////
// Get the data from the instance and populate it into the local buffer
//////////////////////////////////////////////////////////////////////////
HRESULT CRowset::GetInstanceDataToLocalBuffer(CWbemClassWrapper *pInst,HSLOT hSlot,BSTR strQualifier)
{
HRESULT hr = S_OK;
PROWBUFF pRowBuff = NULL;
pRowBuff = GetRowBuffFromSlot( hSlot, TRUE );
if (FAILED( Rebind((BYTE *)pRowBuff )))
{
hr = E_FAIL ;
}
else
//=====================================================
// Reset the column to point to the first column and
// get the data and put it into the buffer
//=====================================================
if( S_OK == (hr = m_pRowData->ResetColumns()))
{
switch(m_uRsType)
{
case PROPERTYQUALIFIER:
hr = m_pMap->GetDataForPropertyQualifier(m_pRowData,pInst,m_strPropertyName,strQualifier,&m_Columns);
break;
case CLASSQUALIFIER:
hr = m_pMap->GetDataForClassQualifier(m_pRowData,pInst,strQualifier,&m_Columns);
break;
case SCHEMA_ROWSET:
hr = m_pMap->GetDataForSchemaInstance(m_pRowData,pInst,&m_Columns);
break;
case 0:
case COMMAND_ROWSET:
case METHOD_ROWSET:
hr = m_pMap->GetDataForInstance(m_pRowData,pInst,&m_Columns);
break;
default:
hr = E_FAIL;
break;
}
}
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Set rowset properties. This is called during initialization of the rowset
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRowset::SetRowsetProperties(const ULONG cPropertySets, const DBPROPSET rgPropertySets[] )
{
HRESULT hr = S_OK;
VARIANT varPropVal;
VariantInit(&varPropVal);
LONG lFlag = 0;
// call the base class implementation for setting properties
hr = SetProperties(cPropertySets,rgPropertySets);
//============================================================================
// call this function to set the DBPROP_UPDATIBILITY to readonly if the Datasource
// open mode is readonly
//============================================================================
if( (hr == S_OK) || (hr == DB_S_ERRORSOCCURRED) )
{
SynchronizeDataSourceMode();
}
//============================================================================
// Get some properties to determine whether to support bookmarks or not
//============================================================================
if( S_OK == GetRowsetProperty(DBPROP_CANSCROLLBACKWARDS,varPropVal) &&
varPropVal.vt == VT_BOOL && varPropVal.boolVal == VARIANT_TRUE)
{
lFlag = lFlag | CANSCROLLBACKWARDS;
}
if( S_OK == GetRowsetProperty(DBPROP_CANFETCHBACKWARDS,varPropVal) &&
varPropVal.vt == VT_BOOL && varPropVal.boolVal == VARIANT_TRUE)
{
lFlag = lFlag | CANFETCHBACKWARDS;
}
if( S_OK == GetRowsetProperty(DBPROP_IRowsetLocate,varPropVal) &&
varPropVal.vt == VT_BOOL && varPropVal.boolVal == VARIANT_TRUE)
{
lFlag = lFlag | IROWSETLOCATE;
}
if( S_OK == GetRowsetProperty(DBPROP_OTHERINSERT,varPropVal) &&
varPropVal.vt == VT_BOOL && varPropVal.boolVal == VARIANT_TRUE)
{
lFlag = lFlag | OTHERINSERT;
}
//============================================================================
// if bookmarks are asked then set the fetchback and scrollback properties to true
//============================================================================
varPropVal.vt = VT_BOOL;
if(IROWSETLOCATE & lFlag )
{
varPropVal.boolVal = VARIANT_TRUE;
SetRowsetProperty(DBPROP_CANFETCHBACKWARDS,varPropVal);
SetRowsetProperty(DBPROP_CANSCROLLBACKWARDS,varPropVal);
SetRowsetProperty(DBPROP_BOOKMARKS,varPropVal);
lFlag = lFlag | CANSCROLLBACKWARDS;
lFlag = lFlag | CANFETCHBACKWARDS;
lFlag = lFlag | BOOKMARKPROP;
}
//============================================================================
// Bookmarks are not supported for qualifier rowsets
//============================================================================
if(m_uRsType == PROPERTYQUALIFIER || m_uRsType == CLASSQUALIFIER)
{
varPropVal.boolVal = VARIANT_FALSE;
SetRowsetProperty(DBPROP_BOOKMARKS,varPropVal);
SetRowsetProperty(DBPROP_IRowsetLocate,varPropVal);
lFlag = lFlag & ~BOOKMARKPROP;
lFlag = lFlag & ~IROWSETLOCATE;
}
VariantClear(&varPropVal);
return hr;
}
///////////////////////////////////////////////////////////////////////////
// Function to Allocate and Iniatialize rowsets for child recordsets //
///////////////////////////////////////////////////////////////////////////
HRESULT CRowset::AllocateAndInitializeChildRowsets()
{
HRESULT hr = E_FAIL;
DBPROPSET *rgPropsets = NULL;
ULONG cProperties = 0;
ULONG nIndex = 0 , nIndex2 = 0;
ULONG lColType = 0;
//===========================================================================================
// if there are nested columns in the rowset and if childrowsets are not already allocated
//===========================================================================================
if(m_cNestedCols > 0 && m_ppChildRowsets == NULL)
{
//=============================================================
// Allocate pointers for the child rowsets
//=============================================================
m_ppChildRowsets = (CBaseRowObj **)new CRowset*[m_cTotalCols];
if(m_ppChildRowsets == NULL)
{
hr = E_OUTOFMEMORY;
}
else
{
//================================================================================
// Get the rowset Properties
//================================================================================
if(S_OK == (hr = m_pIRowsetInfo->GetProperties(cProperties,NULL,&cProperties,&rgPropsets)))
{
for ( nIndex = 0 ; nIndex < m_cTotalCols ; nIndex++)
{
//========================================================================
// if the columntype is of CHAPTER then allocate a rowset and initialize
//========================================================================
if(m_Columns.ColumnFlags(nIndex) & DBCOLUMNFLAGS_ISCHAPTER )
{
lColType = m_pMap->ParseQualifiedNameToGetColumnType(m_Columns.ColumnName(nIndex));
if(lColType == WMI_CLASS_QUALIFIER)
{
m_ppChildRowsets[nIndex] = (CBaseRowObj*) new CRowset(m_pUnkOuter,CLASSQUALIFIER, NULL,m_pCreator, m_pMap);
}
else
if(lColType == WMI_PROPERTY_QUALIFIER)
{
m_ppChildRowsets[nIndex] = (CBaseRowObj*) new CRowset(m_pUnkOuter,PROPERTYQUALIFIER, m_Columns.ColumnName(nIndex-1),m_pCreator, m_pMap);
}
if(m_ppChildRowsets[nIndex] == NULL)
{
hr = E_OUTOFMEMORY;
break;
}
else
{
//===================================================================
// Initialize the rowset properties
//===================================================================
hr = ((CRowset *)m_ppChildRowsets[nIndex])->InitRowset( cProperties, rgPropsets );
m_ppChildRowsets[nIndex]->AddRef();
}
} // if for columntype
else
m_ppChildRowsets[nIndex] = NULL;
} // for
} // GetProperties
//==========================================================================
// Free memory we allocated to by m_pIRowsetInfo->GetProperties
//==========================================================================
m_pUtilProp->m_PropMemMgr.FreeDBPROPSET( cProperties, rgPropsets);
} // if memory for pointers allocated successfully
}
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Get the pointer to the child recordset for the given ordinal
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRowset::GetChildRowset(DBORDINAL ulOrdinal,REFIID riid, IUnknown ** ppIRowset)
{
HRESULT hr = S_OK;
//===============================================================================================
// If row the child rowset pointer is fetched before fetching any rows from the parent rowsets
// then this will be called before allocating the child recordset. SO allocate the child rowsets
//===============================================================================================
if( m_ppChildRowsets == NULL)
{
hr = AllocateAndInitializeChildRowsets();
}
if(SUCCEEDED(hr))
{
hr = DB_E_NOTAREFERENCECOLUMN;
if(m_cNestedCols > 0)
{
if( ulOrdinal > m_cTotalCols)
{
hr = DB_E_BADORDINAL;
}
else
if(m_ppChildRowsets[ulOrdinal] != NULL)
{
hr = m_ppChildRowsets[ulOrdinal]->QueryInterface(riid,(void **)ppIRowset);
}
}
}
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Check if the HCHAPTER passed is valid or not
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRowset::CheckAndInitializeChapter(HCHAPTER hChapter)
{
HRESULT hr = E_FAIL;
if(m_bIsChildRs && m_pChapterMgr->IsExists(hChapter))
{
hr = S_OK;
}
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Function to release the instance pointers when ReleaseRows is called
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRowset::ReleaseInstancePointer(HROW hRow)
{
//========================================================================
// if the recordset is representing a class
//========================================================================
if(m_bIsChildRs == FALSE )
{
m_InstMgr->DeleteInstanceFromList(hRow);
}
//===============================================================================
// if the row is a child recordset then delete the row from the chapter manager
//===============================================================================
if(m_bIsChildRs == TRUE)
{
m_pChapterMgr->DeleteHRow(hRow);
}
return S_OK;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Function to check if the row exist in the chapter or instance manager
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL CRowset::IsRowExists(HROW hRow)
{
BOOL bRet = FALSE;
if( hRow > 0)
{
//========================================================================
// if the recordset is representing a class
//========================================================================
if(m_bIsChildRs == FALSE)
{
bRet = m_InstMgr->IsRowExists(hRow);
}
//===============================================================================
// if the row is a child recordset then delete the row from the chapter manager
//===============================================================================
if(m_bIsChildRs == TRUE)
{
bRet = m_pChapterMgr->IsRowExists(hRow);
}
}
return bRet;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Function to release all the open rows
// This is called from the destructor
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRowset::ReleaseAllRows()
{
DBROWOPTIONS rgRowOptions[1];
DBREFCOUNT rgRefCounts[1];
DBROWSTATUS rgRowStatus[1];
HRESULT hr = S_OK;
//==========================================================
// if there are any rows fetched
//==========================================================
if(!( ( m_bIsChildRs == TRUE && m_pChapterMgr == NULL) ||
( m_bIsChildRs == FALSE && m_InstMgr == NULL)))
{
memset(rgRowOptions,0,sizeof(DBROWOPTIONS));
memset(rgRowStatus,0,sizeof(DBROWSTATUS));
rgRefCounts[0] = 0;
DBCOUNTITEM cRows = 0 , nIndex = 0;
HROW *prghRows = NULL;
//=================================================
// if the rowset is child rowset get the list
// open rowset from the chapter manager
//=================================================
if(m_bIsChildRs)
{
hr = m_pChapterMgr->GetAllHROWs(prghRows,cRows);
}
//=========================================
// else get it from the instance manager
//=========================================
else
{
hr = m_InstMgr->GetAllHROWs(prghRows,cRows);
}
//===============================================
// If there are open rows the release the rows
//===============================================
if(cRows > 0)
{
for(nIndex = 0 ; nIndex < cRows ; nIndex++)
{
//==============================================================
// Release till the reference count on the row goes to zero
// and thus all the resources allocated for the is released
//==============================================================
do
{
hr = m_pIRowset->ReleaseRows(1, &(prghRows[nIndex]),rgRowOptions,rgRefCounts,NULL);
}while(rgRefCounts[0] > 0 && hr == S_OK);
}
//====================================================================================
// delete the memory allocated by the functions which gives the list of open rows
//====================================================================================
if(prghRows != NULL)
{
delete [] prghRows;
prghRows = NULL;
}
}
}
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Function to find whether the slot for the particular row is set
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRowset::IsSlotSet(HSLOT hRow)
{
HSLOT hSlot = -1;
HRESULT hr = E_FAIL;
hSlot = GetSlotForRow(hRow);
// If valid slot
if( (hSlot) >= 0)
{
hr = m_pIAccessor->GetBitArrayPtr()->IsSlotSet(hSlot);
}
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Function to return the slot number of the row
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
HSLOT CRowset::GetSlotForRow(HROW hRow ) // IN Row handle for which slot number is required
{
HSLOT hSlot = -1;
//=================================================================
// if the rowset is a parent rowset then
// get slot number from the instance manager else get it
// from the chapter manager
//=================================================================
if(m_bIsChildRs == FALSE)
{
//=================================================
// Get the slot for the row
//=================================================
hSlot = m_InstMgr->GetSlot(hRow);
}
//=================================================================================
// if rowset is refering to qualifiers then add the row to the particular chapter
//=================================================================================
else
{
//=================================================
// Get the slot for the row
//=================================================
hSlot = m_pChapterMgr->GetSlot(hRow);
}
return hSlot;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Function which fetches data and puts it into the local buffer
// NTRaid: 145773
// 07/18/00
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRowset::GetData(HROW hRow,BSTR strQualifier )
{
CWbemClassWrapper * pInst = NULL;
BSTR strKey;
HSLOT hSlot = 0;
HRESULT hr = S_OK;
PROWBUFF pRowBuff = NULL;
CVARIANT varKey;
HCHAPTER hChapter = 0;
//===================================================================
/// get the instance pointer corresponding to the HROW passed
// if rowset is referiing to a class and not to qualifiers then
//===================================================================
if(m_bIsChildRs == FALSE)
{
pInst = m_InstMgr->GetInstance(hRow);
m_InstMgr->GetInstanceKey(hRow,&strKey);
hSlot = m_InstMgr->GetSlot(hRow);
}
//===================================================================
// if the recordset is a child rs and representing a qualifier
//===================================================================
else
{
hChapter = m_pChapterMgr->GetChapterForHRow(hRow);
if( hChapter <= 0)
{
hr = DB_E_BADCHAPTER;
}
else
{
//===================================================================
// get the instance pointer corresponding to the
//===================================================================
pInst = m_pChapterMgr->GetInstance(hChapter);
m_pChapterMgr->GetInstanceKey(hChapter,&strKey, hRow);
hSlot = m_pChapterMgr->GetSlot(hRow);
}
}
// NTRaid:111830
if(hSlot == 0 || pInst == NULL)
{
hr = DB_E_BADROWHANDLE;
}
else
if ( SUCCEEDED(hr))
{
if(!( m_uRsType == PROPERTYQUALIFIER ||
m_uRsType == CLASSQUALIFIER))
{
assert(strQualifier == NULL);
//===================================================================
// Refresh the instance.
// This is to get the latest instance if modified from another instance
//===================================================================
if(m_ulProps & OTHERUPDATEDELETE)
{
hr = RefreshInstance(pInst);
}
//===================================================================
// Filling data for the bookmark column
//===================================================================
varKey.SetStr(strKey);
}
else
{
// If the otherupdate is true then strQualifier will be NULL
if(m_ulProps & OTHERUPDATEDELETE)
{
// Filling data for the bookmark column
varKey.SetStr(strKey);
}
else
{
// Filling data for the bookmark column
varKey.SetStr(strQualifier);
}
}
if(SUCCEEDED(hr = GetInstanceDataToLocalBuffer(pInst,hSlot,varKey.GetStr())))
{
//===========================================================================
// if there is atleast one row retrieved and there are neseted columns
// then allocate rows for the child recordsets
//===========================================================================
if(m_cNestedCols > 0 )
{
if(m_ppChildRowsets == NULL)
{
hr = AllocateAndInitializeChildRowsets();
}
//=====================================================================
// Fill the HCHAPTERS for the column
//=====================================================================
if( SUCCEEDED(hr))
{
hr = FillHChaptersForRow(pInst,strKey);
}
}
if( SUCCEEDED(hr))
{
//===================================================
// if the class is not representing qualilfiers
//===================================================
if(m_bIsChildRs == FALSE)
{
//=================================================
// Set the slot for the row
//=================================================
hr = m_InstMgr->SetSlot(hRow,hSlot);
}
//=================================================================================
// if rowset is refering to qualifiers then add the row to the particular chapter
//=================================================================================
else
{
//==============================================
// Set the slot for the Row
//==============================================
if(SUCCEEDED(hr = m_pChapterMgr->SetSlot(hRow,hSlot)))
{
m_pChapterMgr->SetInstance(hChapter,pInst, varKey.GetStr() ,hRow);
}
}
if(SUCCEEDED(hr))
{
pRowBuff = GetRowBuff( (ULONG) hRow, TRUE );
// NTRaid:111830
// 06/07/00
if(pRowBuff)
{
//========================================
// Increment the reference count
//========================================
pRowBuff->ulRefCount++;
}
else
{
hr = E_FAIL;
}
}
//==============================================
// Free the string
//==============================================
if(m_bIsChildRs == FALSE)
{
SysFreeString(strKey);
}
} // Succeeded(hr)
}
varKey.Clear();
} // Succeeded(hr)
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Function to update a row to WMI
// NTRaid : 143868
// 07/15/00
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRowset::UpdateRowData(HROW hRow,PACCESSOR pAccessor , BOOL bNewInst)
{
HRESULT hr = S_OK;
PROWBUFF pRowBuff = NULL;
DBORDINAL ibind = 0;
COLUMNDATA * pColumnData = NULL;
CWbemClassWrapper * pInst = NULL;
DBORDINAL icol = 0;
BOOL bRowModified = FALSE;
BSTR bstrColName;
BSTR strQualifierName =Wmioledb_SysAllocString(NULL);
CDataMap dataMap;
VARIANT varData;
LONG lFlavor = 0;
VariantInit(&varData);
DWORD dwCIMType = 0;
//=================================================================================
// get the pointer to the instance
//=================================================================================
if(m_bIsChildRs == FALSE)
{
if( m_uRsType == PROPERTYQUALIFIER ||
m_uRsType == CLASSQUALIFIER )
{
pInst = m_pInstance;
}
else
if( m_uRsType != COLUMNSROWSET && m_uRsType != SCHEMA_ROWSET && m_uRsType != METHOD_ROWSET)
{
pInst = m_InstMgr->GetInstance(hRow);
}
}
else
{
pInst = m_pChapterMgr->GetInstance(m_pChapterMgr->GetChapterForHRow(hRow));
}
//=================================================================================
// Get the pointer to the row data
//=================================================================================
pRowBuff = GetRowBuff((ULONG) hRow, TRUE );
// NTRaid:111823-111825
// 06/07/00
// If the row is not an instance or qualifier
if(pInst == NULL)
{
hr = DB_E_NOTSUPPORTED;
}
else
//=================================================================================
// IF the rowset is a qualifier type rowset
//=================================================================================
if( m_uRsType == PROPERTYQUALIFIER || m_uRsType == CLASSQUALIFIER )
{
//=================================================================================
// get the qualifier name
//=================================================================================
pColumnData = (COLUMNDATA *) (((BYTE *)pRowBuff )+ m_Columns.GetDataOffset(QUALIFIERNAMECOL));
if( pColumnData->pbData == NULL)
{
hr = DB_E_INTEGRITYVIOLATION; // This is because one of the column values expected
// is NULL or EMPTY
bRowModified = TRUE;
}
else
{
strQualifierName = Wmioledb_SysAllocString((WCHAR *)pColumnData->pbData);
//=================================================================================
// Get the qualifier Value
//=================================================================================
pColumnData = (COLUMNDATA *) (((BYTE *)pRowBuff )+ m_Columns.GetDataOffset(QUALIFIERVALCOL));
VariantCopy(&varData,(VARIANT *)pColumnData->pbData);
//=================================================================================
// Get the qualifier flavor
//=================================================================================
pColumnData = (COLUMNDATA *) (((BYTE *)pRowBuff )+ m_Columns.GetDataOffset(QUALIFIERFLAVOR));
lFlavor = pColumnData->pbData !=NULL ? *(LONG *)pColumnData->pbData : 0 ;
if( varData.vt != VT_EMPTY || varData.vt != VT_NULL)
{
//=================================================================================
// Set the qualifier
//=================================================================================
hr = m_pMap->SetQualifier(pInst,m_strPropertyName,strQualifierName,&varData,lFlavor);
if( SUCCEEDED(hr))
{
//=================================================================================
// This is becuase , we are just adding a qualifier not a new instance
//=================================================================================
bNewInst = FALSE;
bRowModified = TRUE;
}
}
else
{
//=================================================================================
// This is because one of the column values expected is NULL or empty
//=================================================================================
hr = DB_E_INTEGRITYVIOLATION;
bRowModified = TRUE;
}
SysFreeString(strQualifierName);
VariantClear(&varData);
}
}
else
for (ibind = 0; ibind < (int)pAccessor->cBindings; ibind++)
{
icol = pAccessor->rgBindings[ibind].iOrdinal;
pColumnData = (COLUMNDATA *) (((BYTE *)pRowBuff )+ m_Columns.GetDataOffset(icol));
//=================================================================================
// If the columndata is modified then
//=================================================================================
if(pColumnData->dwStatus & COLUMNSTAT_MODIFIED)
{
bstrColName = Wmioledb_SysAllocString((OLECHAR *)m_Columns.ColumnName(icol));
// this variable gets value only if the CIMTYPE is array
dwCIMType = -1;
// if the type is array , then get the original CIMTYPE as array type will
// be given out as VT_ARRAY | VT_VARIANT
if(pColumnData->dwType & DBTYPE_ARRAY)
{
dwCIMType = m_Columns.GetCIMType(icol);
}
if( pColumnData->pbData == NULL)
{
varData.vt = VT_NULL;
}
else
{
//=================================================================================
// Call this function to convert the data to the appropriate datatype in a variant
//=================================================================================
dataMap.MapAndConvertOLEDBTypeToCIMType((USHORT)pColumnData->dwType,pColumnData->pbData,pColumnData->dwLength,varData,dwCIMType);
}
if( m_uRsType == 0)
{
//=================================================================================
// Update the property
//=================================================================================
hr = m_pMap->SetProperty(pInst,bstrColName,&varData);
}
pColumnData->dwStatus &= ~COLUMNSTAT_MODIFIED;
VariantClear(&varData);
SysFreeString(bstrColName);
bRowModified = TRUE;
}
}
if(SUCCEEDED(hr) && (bRowModified == TRUE || bNewInst == TRUE))
{
hr = m_pMap->UpdateInstance(pInst , bNewInst);
}
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Function to update a row to WMI
// this is called from Row Object
// NTRaid : 143868
// 07/15/00
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRowset::UpdateRowData(HROW hRow,DBORDINAL cColumns,DBCOLUMNACCESS rgColumns[ ])
{
HRESULT hr = S_OK;
PROWBUFF pRowBuff = NULL;
DBORDINAL lIndex = 0;
COLUMNDATA * pColumnData = NULL;
CWbemClassWrapper * pInst = NULL;
DBORDINAL icol = 0;
BSTR bstrColName;
CDataMap dataMap;
VARIANT varData;
VariantInit(&varData);
LONG lFlavor = 0;
BSTR strQualifierName =Wmioledb_SysAllocString(NULL);
DWORD dwCIMType = 0;
// get the pointer to the instance
if(m_bIsChildRs == FALSE)
{
if( m_uRsType == PROPERTYQUALIFIER ||
m_uRsType == CLASSQUALIFIER )
{
pInst = m_pInstance;
}
else
if( m_uRsType != COLUMNSROWSET && m_uRsType != SCHEMA_ROWSET && m_uRsType != METHOD_ROWSET)
{
pInst = m_InstMgr->GetInstance(hRow);
}
}
else
{
pInst = m_pChapterMgr->GetInstance(m_pChapterMgr->GetChapterForHRow(hRow));
}
//=========================================
// Get the pointer to the row data
//=========================================
pRowBuff = GetRowBuff((ULONG) hRow, TRUE );
// NTRaid:111823-111825
// 06/07/00
// If the row is not an instance or qualifier
if(pInst == NULL)
{
hr = DB_E_NOTSUPPORTED;
}
else
//================================================
// IF the rowset is a qualifier type rowset
//================================================
if( m_uRsType == PROPERTYQUALIFIER || m_uRsType == CLASSQUALIFIER )
{
icol = GetOrdinalFromColName(rgColumns[lIndex].columnid.uName.pwszName);
//===============================================
// Only qualifier value can be modified
//===============================================
if(cColumns == 1 && icol == QUALIFIERVALCOL)
{
//===============================================
// get the qualifier name
//===============================================
pColumnData = (COLUMNDATA *) (((BYTE *)pRowBuff )+ m_Columns.GetDataOffset(QUALIFIERNAMECOL));
if( pColumnData->pbData == NULL)
{
hr = DB_E_INTEGRITYVIOLATION; // This is because one of the column values expected
// is NULL or EMPTY
}
else
{
strQualifierName = Wmioledb_SysAllocString((WCHAR *)pColumnData->pbData);
//===============================================
// Get the qualifier Value
//===============================================
pColumnData = (COLUMNDATA *) (((BYTE *)pRowBuff )+ m_Columns.GetDataOffset(QUALIFIERVALCOL));
VariantCopy(&varData,(VARIANT *)pColumnData->pbData);
//===============================================
// Get the qualifier flavor
//===============================================
pColumnData = (COLUMNDATA *) (((BYTE *)pRowBuff )+ m_Columns.GetDataOffset(QUALIFIERFLAVOR));
lFlavor = pColumnData->pbData !=NULL ? *(LONG *)pColumnData->pbData : 0 ;
if( varData.vt != VT_EMPTY || varData.vt != VT_NULL)
{
//===============================================
// Set the qualifier
//===============================================
hr = m_pMap->SetQualifier(pInst,m_strPropertyName,strQualifierName,&varData,lFlavor);
}
else
{
//========================================================
// This is because one of the column values expected
//is NULL or EMPTY
//========================================================
hr = DB_E_INTEGRITYVIOLATION;
}
SysFreeString(strQualifierName);
VariantClear(&varData);
}
}
else
{
//====================================================
// Only qualifier value can be modified
//====================================================
hr = E_FAIL;
}
}
else
for (lIndex = 0; lIndex < cColumns; lIndex++)
{
icol = GetOrdinalFromColName(rgColumns[lIndex].columnid.uName.pwszName);
//=============================================================================
// If the column is not present in the rowset it is already updated in the
// row. This will happen only when this method is called from the row object
//=============================================================================
if( (DB_LORDINAL)icol < 0)
{
continue;
}
pColumnData = (COLUMNDATA *) (((BYTE *)pRowBuff )+ m_Columns.GetDataOffset(icol));
//=============================================================================
// If the columndata is modified then
//=============================================================================
if(pColumnData->dwStatus & COLUMNSTAT_MODIFIED)
{
bstrColName = Wmioledb_SysAllocString((OLECHAR *)m_Columns.ColumnName(icol));
dwCIMType = -1;
//===================================================================================
// if the type is array , then get the original CIMTYPE as array type will
// be given out as VT_ARRAY | VT_VARIANT
//===================================================================================
if(pColumnData->dwType & DBTYPE_ARRAY)
{
dwCIMType = m_Columns.GetCIMType(icol);
}
if( pColumnData->pbData == NULL)
{
varData.vt = VT_NULL;
}
else
{
//===================================================================================
// Call this function to convert the data to the appropriate datatype in a variant
//===================================================================================
dataMap.MapAndConvertOLEDBTypeToCIMType((USHORT)pColumnData->dwType,pColumnData->pbData,pColumnData->dwLength,varData,dwCIMType);
}
//================================
// Update the property
//================================
if( m_uRsType == 0)
{
//==================================
// Update the property
//==================================
hr = m_pMap->SetProperty(pInst,bstrColName,&varData);
}
pColumnData->dwStatus &= ~COLUMNSTAT_MODIFIED;
VariantClear(&varData);
SysFreeString(bstrColName);
}
}
//=============================================================================
// If everything is fine then update the instance
//=============================================================================
if( hr == S_OK)
{
hr = m_pMap->UpdateInstance(pInst , FALSE);
}
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Function to delete a instance(Row) from WMI
// NTRaid : 143524
// 07/15/00
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRowset::DeleteRow(HROW hRow,DBROWSTATUS * pRowStatus)
{
HRESULT hr = S_OK;
DBROWOPTIONS rgRowOptions[1];
ULONG rgRefCounts[1];
DBROWSTATUS rgRowStatus[1];
CWbemClassWrapper *pInst = NULL;
VARIANT varProp;
PROWBUFF pRowBuff = NULL;
COLUMNDATA * pColumnData = NULL;
VariantInit(&varProp);
memset(rgRowOptions,0,sizeof(DBROWOPTIONS));
memset(rgRowStatus,0,sizeof(DBROWSTATUS));
rgRefCounts[0] = 0;
if(pRowStatus != NULL)
*pRowStatus = DBROWSTATUS_S_OK;
//===================================================================
/// get the instance pointer corresponding to the HROW passed
// if rowset is referiing to a class and not to qualifiers then
//===================================================================
if(m_bIsChildRs == FALSE)
{
if( m_uRsType == PROPERTYQUALIFIER ||
m_uRsType == CLASSQUALIFIER )
{
pInst = m_pInstance;
}
else
if( m_uRsType != COLUMNSROWSET && m_uRsType != SCHEMA_ROWSET && m_uRsType != METHOD_ROWSET)
{
pInst = m_InstMgr->GetInstance(hRow);
}
}
//===================================================================
// if the recordset is a child rs and representing a qualifier
//===================================================================
else
{
//===================================================================
// get the instance pointer corresponding to the
//===================================================================
pInst = m_pChapterMgr->GetInstance(m_pChapterMgr->GetChapterForHRow(hRow));
}
// NTRaid:111800
// 06/07/00
// If the row is not an instance or qualifier
if(pInst == NULL)
{
hr = DB_E_NOTSUPPORTED;
}
else
// NTRaid : 143425
// 07/17/00
if( m_uRsType == PROPERTYQUALIFIER ||
m_uRsType == CLASSQUALIFIER )
{
// Delete qualifier
//=========================================
// Get the pointer to the row data
//=========================================
pRowBuff = GetRowBuff(hRow, TRUE );
//=============================================
// Get the Data for the qualifier name
//=============================================
pColumnData = (COLUMNDATA *) (((BYTE *)pRowBuff )+ m_Columns.GetDataOffset(QUALIFIERNAMECOL));
//================================================================================
// This will always of type VT_BSTR as this column represents the QUALIFER name
//================================================================================
if(pColumnData->dwType == VT_BSTR)
{
hr = m_pMap->DeleteQualifier(pInst,(BSTR)pColumnData->pbData,(m_uRsType == CLASSQUALIFIER),m_strPropertyName);
}
}
else
if( m_uRsType != COLUMNSROWSET && m_uRsType != SCHEMA_ROWSET && m_uRsType != METHOD_ROWSET)
{
//===================================
// Delete the Instance
//===================================
hr = m_pMap->DeleteInstance(pInst);
}
else
{
hr = WBEM_E_PROVIDER_NOT_CAPABLE;
}
//===================================================================
// If delete is not allowed if it is not capable of deletion then
// set the updatibility property of the rowset
//===================================================================
if( hr == WBEM_E_PROVIDER_NOT_CAPABLE)
{
GetRowsetProperty(DBPROP_UPDATABILITY,varProp);
varProp.lVal ^= DBPROPVAL_UP_DELETE;
SetRowsetProperty(DBPROP_UPDATABILITY,varProp);
hr = DB_E_NOTSUPPORTED;
if(pRowStatus)
{
*pRowStatus = DBROWSTATUS_E_INTEGRITYVIOLATION;
}
}
else
if(FAILED(hr) && (pRowStatus != NULL))
{
if(pRowStatus)
{
*pRowStatus = DBROWSTATUS_E_FAIL;
}
}
if( hr == S_OK)
{
//====================================
// Set the row status to DELETED
//====================================
SetRowStatus(hRow,DBROWSTATUS_E_DELETED);
if(pRowStatus)
{
*pRowStatus = DBROWSTATUS_S_OK;
}
}
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Set the status of a row
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
void CRowset::SetRowStatus(HROW hRow , DBSTATUS dwStatus)
{
if(m_bIsChildRs == FALSE)
{
m_InstMgr->SetRowStatus(hRow , dwStatus);
}
else
{
m_pChapterMgr->SetRowStatus(hRow , dwStatus);
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Gets the current status of the row
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
DBSTATUS CRowset::GetRowStatus(HROW hRow )
{
DBSTATUS dwStatus = DBROWSTATUS_E_FAIL;
if(m_bIsChildRs == FALSE)
{
dwStatus = m_InstMgr->GetRowStatus(hRow);
}
else
{
dwStatus = m_pChapterMgr->GetRowStatus(hRow);
}
return dwStatus;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Gets Key value of a instance
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
void CRowset::GetInstanceKey(HROW hRow , BSTR *strKey)
{
CWbemClassWrapper *pInst = NULL;
//====================================
// get the pointer to the instance
//====================================
if(m_bIsChildRs == FALSE)
{
pInst = m_InstMgr->GetInstance(hRow);
m_InstMgr->GetInstanceKey(hRow,strKey);
}
else
{
pInst = m_pChapterMgr->GetInstance(m_pChapterMgr->GetChapterForHRow(hRow));
m_pChapterMgr->GetInstanceKey(hRow,strKey);
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Set the status of a rowset or a chapter
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
void CRowset::SetStatus(HCHAPTER hChapter , DWORD dwStatus)
{
if(m_bIsChildRs == FALSE)
{
//================================
// skip caused END_OF_ROWSET
//================================
m_dwStatus |= dwStatus;
}
else
{
//========================================================================
// set the status of the chapter to end of rowset
//========================================================================
m_pChapterMgr->SetChapterStatus(hChapter , dwStatus);
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Gets the status of a rowset or a chapter
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
DBSTATUS CRowset::GetStatus(HCHAPTER hChapter)
{
DBSTATUS dwStatus = 0;
if(m_bIsChildRs == FALSE)
{
//================================
// skip caused END_OF_ROWSET
//================================
dwStatus = m_dwStatus;
}
else
{
//========================================================================
// set the status of the chapter to end of rowset
//========================================================================
dwStatus = m_pChapterMgr->GetChapterStatus(hChapter );
}
return dwStatus;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Adds a new instance to the class
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRowset::InsertNewRow(CWbemClassWrapper **ppNewInst)
{
HRESULT hr = S_OK;
switch(m_uRsType)
{
case PROPERTYQUALIFIER:
break;
case CLASSQUALIFIER:
break;
case SCHEMA_ROWSET:
hr = DB_E_NOTSUPPORTED;
break;
case 0:
hr = m_pMap->AddNewInstance(ppNewInst);
break;
default:
hr = E_FAIL;
}
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////
// Function which releases the rowdata ( does not release the row)
// release the memory allocated for the row and also the slot allocated for the row
///////////////////////////////////////////////////////////////////////////////////////
HRESULT CRowset::ReleaseRowData(HROW hRow,BOOL bReleaseSlot)
{
HSLOT hSlot = 0;
HRESULT hr = S_OK;
//===================================================================
/// get the handle to slot
//===================================================================
if(m_bIsChildRs == FALSE)
{
//===================================================================
// get the handle to slot for the instance
//===================================================================
hSlot = m_InstMgr->GetSlot(hRow);
if(bReleaseSlot)
{
// Reset the HSLOT in the chapter Manager
m_InstMgr->SetSlot(hRow , -1);
}
}
//===================================================================
// if the recordset is a child rs and representing a qualifier
//===================================================================
else
{
//===================================================================
// get the handle to slot for the instance
//===================================================================
hSlot = m_pChapterMgr->GetSlot(hRow);
//================================================
// Reset the HSLOT in the chapter Manager
//================================================
if(bReleaseSlot)
{
m_pChapterMgr->SetSlot(hRow ,-1);
}
}
if( hSlot > 0)
{
if (FAILED( Rebind((BYTE *) GetRowBuffFromSlot( hSlot, TRUE ))))
{
hr = E_FAIL ;
}
else
{
//===========================================================
// release the memory allocated for the different columns
//===========================================================
m_pRowData->ReleaseRowData();
//==============================
// release the slots
//==============================
if(bReleaseSlot)
{
ReleaseSlots( m_pIBuffer, hSlot, 1 );
}
}
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// Virtual Overidden function which is called from IColumnInfo to get the column information
/////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRowset::GetColumnInfo(DBORDINAL* pcColumns, DBCOLUMNINFO** prgInfo,WCHAR** ppStringsBuffer)
{
ULONG icol = 0;
DBCOLUMNINFO* rgdbcolinfo = NULL;
WCHAR* pstrBuffer = NULL;
WCHAR* pstrBufferForColInfo = NULL;
HRESULT hr = S_OK;
DBCOUNTITEM nTotalCols = m_cTotalCols;
BOOL bFlag = TRUE;
if(!(m_ulProps & BOOKMARKPROP))
{
nTotalCols--;
bFlag = FALSE;
}
//=======================================
// Copy the columninformation
//=======================================
if(SUCCEEDED(hr = m_Columns.CopyColumnInfoList(rgdbcolinfo,bFlag)))
{
//===========================================
// Copy the heap for column names.
//===========================================
if ( m_Columns.ColumnNameListStartingPoint() != NULL){
ptrdiff_t dp;
hr = m_Columns.CopyColumnNamesList(pstrBuffer);
dp = (LONG_PTR) pstrBuffer - (LONG_PTR) (m_Columns.ColumnNameListStartingPoint());
dp >>= 1;
//===========================================
// Loop through columns and adjust pointers
// to column names.
//===========================================
for ( icol =0; icol < nTotalCols; icol++ )
{
if ( rgdbcolinfo[icol].pwszName )
{
rgdbcolinfo[icol].pwszName += dp;
}
}
}
//==============================
// Set the output parameters
//==============================
*prgInfo = &rgdbcolinfo[0];
*ppStringsBuffer = pstrBuffer;
*pcColumns = nTotalCols;
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// get the instance pointer of a particular row
/////////////////////////////////////////////////////////////////////////////////////////////////////////
CWbemClassWrapper *CRowset::GetInstancePtr(HROW hRow)
{
CWbemClassWrapper *pInst = NULL;
if(m_bIsChildRs == FALSE)
{
pInst = m_InstMgr->GetInstance(hRow);
}
else
{
pInst = m_pChapterMgr->GetInstance(m_pChapterMgr->GetChapterForHRow(hRow));
}
return pInst;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// Get the qualifier name which will be present in the first column for
// qualifier rowset
/////////////////////////////////////////////////////////////////////////////////////////////////////////
void CRowset::GetQualiferName(HROW hRow,BSTR &strBookMark)
{
PROWBUFF pRowBuff = NULL;
PCOLUMNDATA pColumnData = NULL;
pRowBuff = GetRowBuff( (ULONG) hRow, TRUE );
pColumnData = (COLUMNDATA *) ((BYTE *) pRowBuff + m_Columns.GetDataOffset(0));
//===================================================================
// FIXXX More work is to be done on this
//===================================================================
if( pColumnData->dwType == DBTYPE_BSTR )
strBookMark = Wmioledb_SysAllocString((WCHAR *)(pColumnData->pbData));
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Generate a new HCHAPTER for the current row and add it to the CHAPTER manager
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRowset::FillHChaptersForRow(CWbemClassWrapper *pInst, BSTR strKey)
{
HRESULT hr = S_OK;
ULONG nIndex = 0;
PCOLUMNDATA * pColumnData = NULL;
CVARIANT var;
HCHAPTER hChapter = 0;
//============================================================================
// if there are nested columns in the rowset
//============================================================================
if(m_cNestedCols > 0)
{
for ( ULONG nIndex = 0 ; nIndex < m_cTotalCols ; nIndex++)
{
//============================================================================
// if the columntype is of CHAPTER then allocate a rowset and initialize
//============================================================================
if(m_Columns.ColumnFlags(nIndex) & DBCOLUMNFLAGS_ISCHAPTER )
{
hChapter = GetNextHChapter();
var.SetLONG((LONG)hChapter);
if(FAILED(hr = m_pRowData->CommitColumnToRowData(var,nIndex,VT_UI4)))
{
break;
}
//============================================================================
// Add the chapter to the corresponding child recordset
//============================================================================
m_ppChildRowsets[nIndex]->m_pChapterMgr->AddChapter(hChapter);
m_ppChildRowsets[nIndex]->m_pChapterMgr->SetInstance(hChapter,pInst,strKey);
} // if for columntype
} // for
}
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Function to add reference to a chapter
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRowset::AddRefChapter(HCHAPTER hChapter,DBREFCOUNT * pcRefCount)
{
HRESULT hr = E_UNEXPECTED;
ULONG ulRet = -1;
//===========================================
// if the rowset is a child rowset
//===========================================
if(m_bIsChildRs == TRUE)
{
//=======================================
// If chapter belongs to the rowset
//=======================================
if(m_pChapterMgr->IsExists(hChapter) == FALSE)
{
hr = DB_E_BADCHAPTER;
}
else
{
//===================================
// Add reference to the chapter
//===================================
ulRet = m_pChapterMgr->AddRefChapter(hChapter);
if( ulRet > 0)
{
hr = S_OK;
}
}
}
if(pcRefCount != NULL)
{
*pcRefCount = ulRet;
}
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Function to release reference to a chapter
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRowset::ReleaseRefChapter(HCHAPTER hChapter , ULONG * pcRefCount)
{
HRESULT hr = E_UNEXPECTED;
ULONG ulRet = -1;
//=======================================
// if the rowset is a child rowset
//=======================================
if(m_bIsChildRs == TRUE)
{
//===================================
// If chapter belongs to the rowset
//===================================
if(m_pChapterMgr->IsExists(hChapter) == FALSE)
{
hr = DB_E_BADCHAPTER;
}
else
{
//======================================
// Release reference to the chapter
//======================================
ulRet = m_pChapterMgr->ReleaseRefChapter(hChapter);
if(((LONG)ulRet) >= 0)
{
hr = S_OK;
}
}
}
if(pcRefCount != NULL)
{
*pcRefCount = ulRet;
}
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Get the number of rows in the rowset
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRowset::GetRowCount()
{
HRESULT hr = S_OK;
switch(m_uRsType)
{
case PROPERTYQUALIFIER:
m_lRowCount = -1;
break;
case CLASSQUALIFIER:
m_lRowCount = -1;
break;
case SCHEMA_ROWSET:
m_lRowCount = -1;
break;
case 0:
case COMMAND_ROWSET:
hr = m_pMap->GetInstanceCount(m_lRowCount);
break;
default:
hr = E_FAIL;
}
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Get the Data to local buffer for a particular row
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRowset::GetDataToLocalBuffer(HROW hRow)
{
HSLOT hSlot = 0;
HRESULT hr = S_OK;
BSTR strBookMark = Wmioledb_SysAllocString(NULL);
if(m_uRsType == PROPERTYQUALIFIER ||
m_uRsType == CLASSQUALIFIER )
{
GetQualiferName(hRow,strBookMark);
}
hSlot = GetSlotForRow(hRow);
if (FAILED( Rebind((BYTE *) GetRowBuffFromSlot( hSlot, TRUE ))))
{
hr = E_FAIL;
}
else
{
//======================================
// Release the previous row data
//======================================
m_pRowData->ReleaseRowData();
//======================================
// Get the data for the current row
//======================================
if(SUCCEEDED(hr = GetData(hRow,strBookMark)))
{
m_ulLastFetchedRow = hRow;
}
if( strBookMark != NULL)
{
SysFreeString(strBookMark);
}
}
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Check if a particular instance is deleted.
// A particular instance is deleted , if it is deleted from WMI and appropriate properties are
// set for different cursor types
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL CRowset::IsInstanceDeleted(CWbemClassWrapper *pInst)
{
DWORD dwStatus = m_pMap->GetInstanceStatus(pInst);
BOOL bRet = FALSE;
//===================================
// if the cursor is dynamic
//===================================
if((m_ulProps & OTHERINSERT) && dwStatus != DBSTATUS_S_OK)
{
bRet = TRUE;
}
else
if(((m_ulProps & OWNUPDATEDELETE) && dwStatus == DBROWSTATUS_E_DELETED) ||
((m_ulProps & OTHERUPDATEDELETE) && dwStatus == DBSTATUS_E_UNAVAILABLE))
{
bRet = TRUE;
}
return bRet;
}
void CRowset::SetCurFetchDirection(FETCHDIRECTION FetchDir)
{
m_FetchDir = FetchDir;
m_pMap->SetCurFetchDirection(FetchDir);
}