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.
 
 
 
 
 
 

3180 lines
90 KiB

///////////////////////////////////////////////////////////////////////////////////
//
// Microsoft WMIOLE DB Provider
// (C) Copyright 1999 Microsoft Corporation. All Rights Reserved.
//
// CRow object implementation
//
//
///////////////////////////////////////////////////////////////////////////////////
#include "headers.h"
#include "WmiOleDBMap.h"
#define PATHSEPARATOR L"/"
/////////////////////////////////////////////////////////////////////////////////////////////////
// Constructor for this class
/////////////////////////////////////////////////////////////////////////////////////////////////
CRow::CRow(LPUNKNOWN pUnkOuter,CRowset *pRowset,PCDBSESSION pObj,CWbemConnectionWrapper *pCon ) : CBaseRowObj(pUnkOuter)
{
InitVars();
m_pMap = pRowset->GetWmiOleDBMap();
m_pMap->AddRef();
m_pUtilProp = pRowset->m_pUtilProp;
m_pCreator = pObj;
m_pSourcesRowset = pRowset;
m_pSourcesRowset->AddRef();
m_pCreator->GetOuterUnknown()->AddRef();
//===============================================
// Add this rowset ot list of open rowset
//===============================================
m_pCreator->AddRowset(this);
pRowset->QueryInterface(IID_IConvertType, (void **)&m_pIConvertType);
m_pCon = pCon;
InterlockedIncrement(&g_cObj);
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// Constructor for this class. This is called from the root binder object
/////////////////////////////////////////////////////////////////////////////////////////////////
CRow::CRow(LPUNKNOWN pUnkOuter, PCDBSESSION pObj ) : CBaseRowObj(pUnkOuter)
{
InitVars();
m_pCreator = pObj;
m_pSourcesRowset = NULL;
m_pCreator->GetOuterUnknown()->AddRef();
//===============================================
// Add this rowset ot list of open rowset
//===============================================
m_pCreator->AddRowset(this);
InterlockedIncrement(&g_cObj);
}
void CRow::InitVars()
{
m_pMap = NULL;
m_pUtilProp = NULL;
m_pCreator = NULL;
m_pSourcesRowset = NULL;
m_pRowData = NULL;
m_pIBuffer = NULL;
m_strURL = NULL;
m_strKey = NULL;
m_rgbRowData = NULL;
m_pRowColumns = NULL;
m_pInstance = NULL;
m_pIColumnsInfo = NULL;
m_pIRow = NULL;
m_pIConvertType = NULL;
m_pIGetSession = NULL;
m_pIRowChange = NULL;
m_pIScopedOperations = NULL;
m_cTotalCols = 0;
m_cCols = 0;
m_cNestedCols = 0;
m_cRef = 0;
m_cbRowSize = 0;
m_ulProps = 0;
m_hRow = 0;
m_dwStatus = 0;
m_bHelperFunctionCreated = FALSE;
m_bClassChanged = FALSE;
m_rowType = ROW_INSTANCE;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// Destructor for this class
/////////////////////////////////////////////////////////////////////////////////////////////////
CRow::~CRow()
{
if (NULL != m_pIBuffer){
ReleaseSlotList( m_pIBuffer );
}
//===============================================================
// NOTE: m_pMap releases the class ptr in destructor and if
// the reference count goes to 0 then this will released
//===============================================================
m_pMap->Release();
// If the row object is created from a rowset object then release all the interfaces
if(m_pSourcesRowset != NULL)
{
m_pIConvertType->Release();
m_pSourcesRowset->Release();
SAFE_DELETE_PTR(m_pRowColumns);
}
else
{
SAFE_DELETE_PTR( m_pIConvertType );
SAFE_DELETE_PTR( m_pUtilProp );
}
//===============================================================
// Free contained interfaces
//===============================================================
SAFE_DELETE_PTR( m_pIColumnsInfo );
SAFE_DELETE_PTR( m_pIRow );
SAFE_DELETE_PTR( m_pIGetSession );
SAFE_DELETE_PTR( m_pIRowChange );
SAFE_DELETE_PTR(m_pRowData);
SAFE_DELETE_PTR(m_pIScopedOperations);
SAFE_DELETE_PTR(m_pISupportErrorInfo);
/*
if(m_pSourcesRowset == NULL)
{
SAFE_DELETE_PTR(m_pInstance);
}
*/
//===============================================================
// Decrement the DBSession Count. GetSpecification is not
// possible anymore
//===============================================================
if( m_pCreator ){
//===========================================================
// Mark the session as not having an open rowset anymore
//===========================================================
m_pCreator->GetOuterUnknown()->Release();
}
SAFE_DELETE_ARRAY(m_strKey);
SAFE_DELETE_ARRAY(m_strURL);
//===============================================================
// 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.
//
// 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 CRow::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_IColumnsInfo)
{
*ppv = (LPVOID) m_pIColumnsInfo;
}
else if (riid == IID_IConvertType)
{
*ppv = (LPVOID) m_pIConvertType;
}
else if (riid == IID_IRow)
{
*ppv = (LPVOID) m_pIRow;
}
else if (riid == IID_IGetSession)
{
*ppv = (LPVOID) m_pIGetSession;
}
else if (riid == IID_IRowChange)
{
*ppv = (LPVOID) m_pIRowChange;
}
else if( riid == IID_ISupportErrorInfo)
{
*ppv = (LPVOID)m_pISupportErrorInfo;
}
else if(riid == IID_IScopedOperations || riid == IID_IBindResource)
{
*ppv = (LPVOID)m_pIScopedOperations;
}
//======================================================
// 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
//
// Current reference count
//
/////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_( ULONG ) CRow::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 ) CRow::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;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// The first function called for the row for initialization of the class
/////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRow::InitRow(HROW hRow ,
CWbemClassWrapper *pInst ,
ROWCREATEBINDFLAG rowCreateFlag)
{
HRESULT hr = S_OK;
DBCOLUMNINFO * pCol = NULL;
CURLParser urlParser;
m_hRow = hRow;
m_pInstance = (CWbemClassInstanceWrapper *)pInst;
//=================================================
// If the class is not created by the rowset then
//=================================================
if(m_pSourcesRowset == NULL)
{
BSTR strTemp;
strTemp = Wmioledb_SysAllocString(m_strKey);
urlParser.SetPath(strTemp);
SysFreeString(strTemp);
if(urlParser.GetURLType() == URL_EMBEDEDCLASS)
{
GetEmbededInstancePtrAndSetMapClass(&urlParser);
}
else
{
VARIANT varDataSrc;
VariantInit(&varDataSrc);
m_pInstance = NULL;
strTemp = Wmioledb_SysAllocString(m_strKey);
// If the object path is same as the data src then the object has
// to be obtained by just QI on the IWbemServicesEx pointer
if(SUCCEEDED(hr = m_pCreator->GetDataSrcProperty(DBPROP_INIT_DATASOURCE , varDataSrc)) &&
varDataSrc.vt == VT_BSTR && varDataSrc.bstrVal != NULL)
{
if(_wcsicmp(m_strKey,varDataSrc.bstrVal) == 0)
{
SAFE_FREE_SYSSTRING(strTemp);
}
}
m_pInstance = (CWbemClassInstanceWrapper *)m_pMap->GetInstance(strTemp);
SysFreeString(strTemp);
}
urlParser.GetURL(strTemp);
m_strURL = new WCHAR[SysStringLen(strTemp) + 1];
// NTRaid:111801
// 06/07/00
if(m_strURL)
{
memset(m_strURL,0,(SysStringLen(strTemp) + 1) * sizeof(WCHAR));
memcpy(m_strURL,strTemp,SysStringLen(strTemp) * sizeof(WCHAR));
if( rowCreateFlag == ROWCREATE && m_pInstance != NULL)
{
hr = DB_E_RESOURCEEXISTS;
}
else
{
//=================================================
// If an existing instance is to be created
//=================================================
if( rowCreateFlag == ROWCREATE || rowCreateFlag == ROWOVERWRITE )
{
//======================================================
// If instance already exists then delete the instance
//======================================================
if( m_pInstance != NULL)
{
m_pMap->DeleteInstance(m_pInstance);
m_pInstance = NULL;
}
//===========================
// Create instance
//===========================
hr = CreateNewRow(&m_pInstance);
}
//=================================================================
// If instance is pointed by the path is not found return error
//=================================================================
if( m_pInstance == NULL)
{
hr = DB_E_NOTFOUND;
}
else
{
/* //====================================================================
/// Get property and Set Serach Preferences
//====================================================================
hr = SetSearchPreferences();
//===================================================================================
// Get the column information
//===================================================================================
if(SUCCEEDED(hr = CBaseRowObj::GetColumnInfo()))
{
m_cTotalCols--; // Decrementing so as not to take into account the bookmark column
//===========================================================================
// Initialize the columns representing the qualifiers and embeded classes
//===========================================================================
if(m_cNestedCols > 0)
for ( int iCol = 1 ; iCol < (int)m_Columns.GetTotalNumberOfColumns(); iCol++)
{
pCol = m_Columns.GetColInfo(iCol);
if( pCol->wType == DBTYPE_HCHAPTER)
{
pCol->wType = DBTYPE_UI4;
pCol->ulColumnSize = sizeof(ULONG);
pCol->dwFlags = DBCOLUMNFLAGS_ISCOLLECTION;
}
}
} // Succeeded(GetCOlumnInfo())
*/
hr = S_OK;
} // Else if instance pointed by path not found
} // else of if( rowCreateFlag == ROWCREATE && m_pInstance != NULL)
} // if(m_strUrl)
else
{
hr = E_OUTOFMEMORY;
}
}
else
{
CBSTR strTemp;
if(SUCCEEDED(hr = ((CWbemClassInstanceWrapper *)pInst)->GetKey(strTemp)))
{
m_strKey = new WCHAR [ SysStringLen(strTemp) + 1];
wcscpy(m_strKey,strTemp);
urlParser.SetPath(strTemp);
strTemp.Clear();
strTemp.Unbind();
urlParser.GetURL((BSTR &)strTemp);
m_strURL = new WCHAR[ SysStringLen(strTemp) + 1];
memset(m_strURL,0,(SysStringLen(strTemp) + 1) * sizeof(WCHAR));
memcpy(m_strURL,strTemp,SysStringLen(strTemp) * sizeof(WCHAR));
}
}
if(SUCCEEDED(hr))
{
//===========================================================================
// Call this function to allocate memory for all the contained interfaces
// and utility classes
//===========================================================================
if(SUCCEEDED(hr = AllocateInterfacePointers()))
{
if(m_pSourcesRowset != NULL)
{
m_cTotalCols = m_pSourcesRowset->m_Columns.GetTotalNumberOfColumns();
hr = GetRowColumnInfo();
}
else
{
//====================================================================
/// Get property and Set Serach Preferences
//====================================================================
hr = SetSearchPreferences();
//===================================================================================
// Get the column information
//===================================================================================
if(SUCCEEDED(hr = CBaseRowObj::GetColumnInfo()))
{
m_cTotalCols--; // Decrementing so as not to take into account the bookmark column
//===========================================================================
// Initialize the columns representing the qualifiers and embeded classes
//===========================================================================
if(m_cNestedCols > 0)
for ( int iCol = 1 ; iCol < (int)m_Columns.GetTotalNumberOfColumns(); iCol++)
{
pCol = m_Columns.GetColInfo(iCol);
if( pCol->wType == DBTYPE_HCHAPTER)
{
pCol->wType = DBTYPE_UI4;
pCol->ulColumnSize = sizeof(ULONG);
pCol->dwFlags = DBCOLUMNFLAGS_ISCOLLECTION | DBCOLUMNFLAGS_ISCHAPTER;
}
}
} // Succeeded(GetCOlumnInfo())
m_pRowColumns = &m_Columns;
}
} // if Succeeded(hr)
} // If Succeeded(hr)
if(SUCCEEDED(hr))
{
//==========================================================
// Call this function to initialize the ISupportErrorInfo;
//==========================================================
hr = AddInterfacesForISupportErrorInfo();
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// This first function called for the row for initialization of the class when a row is
// not created from rowset object
// An overloaded function
/////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRow::InitRow(LPWSTR strPath,
LPWSTR strTableID ,
DWORD dwFlags,
ROWCREATEBINDFLAG rowCreateFlag)
{
HRESULT hr = S_OK;
//=========================================================
// Call this function to Initialize and allocate WMIOledb
//=========================================================
hr = InitializeWmiOledbMap(strPath,strTableID,dwFlags);
if( SUCCEEDED(hr))
{
hr = InitRow(0,0,rowCreateFlag);
}
return hr;
}
////////////////////////////////////////////////////////////////////////////////////////////
// Function to allocate contained interface pointers and also some utility classes
////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRow::AllocateInterfacePointers()
{
HRESULT hr = S_OK;
if(m_pSourcesRowset == NULL)
{
m_pIConvertType = new CImpIConvertType(this);
m_pUtilProp = new CUtilProp;
// NTRaid: 136443
// 07/05/00
if(m_pUtilProp)
{
hr = m_pUtilProp->FInit(ROWSETPROP);
}
else
{
hr = E_OUTOFMEMORY;
}
}
//=========================================================================
// if row is created from a rowset then create a columninfo manager
// instance , passing the source rowset as a parameter to constructor
//=========================================================================
else
{
m_pRowColumns = new cRowColumnInfoMemMgr(&m_pSourcesRowset->m_Columns);
}
if(SUCCEEDED(hr))
{
m_pIColumnsInfo = new CImpIColumnsInfo( this );
m_pIRow = new CImpIRow( this );
m_pIGetSession = new CImpIGetSession( this );
m_pIRowChange = new CImpIRowChange( this );
m_pISupportErrorInfo = new CImpISupportErrorInfo(this);
m_pIScopedOperations = new CImpIScopedOperations(this);
if( ! (m_pIColumnsInfo && m_pUtilProp && m_pIRow && m_pIGetSession && m_pIRowChange && m_pIConvertType && m_pIScopedOperations))
{
hr = E_OUTOFMEMORY;
}
}
return hr;
}
////////////////////////////////////////////////////////////////////////////////////////////
// Function to allocate CWmiOledbMap class if row is not created from rowset
////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRow::InitializeWmiOledbMap(LPWSTR strPath,
LPWSTR strTableID ,
DWORD dwFlags)
{
HRESULT hr = S_OK;
assert(m_pSourcesRowset == NULL);
CURLParser urlParser;
CBSTR strTemp;
if(strPath == NULL )
{
hr = E_INVALIDARG;
}
else
{
LONG lObjectType = -1;
strTemp.SetStr(strPath);
urlParser.SetPath(strTemp);
lObjectType = urlParser.GetURLType();
if(lObjectType == URL_DATASOURCE && strTableID == NULL)
{
hr = E_INVALIDARG;
}
if(lObjectType == URL_DATASOURCE) // or scope
{
m_rowType = ROW_SCOPE;
}
}
if(SUCCEEDED(hr))
{
dwFlags = dwFlags == -1 ? GetQualifierFlags(): dwFlags;
if(m_rowType == ROW_SCOPE) // this happenes only the opened scope is a namespace
{
/*// m_pMap = new CWmiOleDBMap( strPath,
// m_pCon == NULL ?m_pCreator->m_pCDataSource->m_pWbemWrap: m_pCon);
if(m_pMap)
{
// hr = m_pMap->FInit( strPath,m_pCon == NULL ?m_pCreator->m_pCDataSource->m_pWbemWrap: m_pCon);
}
else
{
hr = E_OUTOFMEMORY;
}
*/ }
else
{
m_pMap = new CWmiOleDBMap;
if(m_pMap)
{
hr = m_pMap->FInit(dwFlags,strTableID,m_pCon == NULL ?m_pCreator->m_pCDataSource->m_pWbemWrap: m_pCon);
}
else
{
hr = E_OUTOFMEMORY;
}
}
if(SUCCEEDED(hr))
{
VARIANT varValue;
VariantInit(&varValue);
// Bug which not able to get system properties from Row object
// NTRaid: 145684
// 05/06/00
//===========================================================================================
// Get the DataSource property to check if system Properties is to be fetched?
//===========================================================================================
if(SUCCEEDED(hr = m_pCreator->GetDataSrcProperty(DBPROP_WMIOLEDB_SYSTEMPROPERTIES,varValue)))
{
if( varValue.boolVal == VARIANT_TRUE)
{
m_pMap->SetSytemPropertiesFlag(TRUE);
}
m_strKey = new WCHAR [wcslen(strPath) + 1];
if(m_strKey == NULL)
{
hr = E_OUTOFMEMORY;
}
else
{
wcscpy(m_strKey,strPath);
m_pMap->AddRef();
}
}
VariantClear(&varValue);
}
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
// Function to add interfaces to ISupportErrorInfo interface
/////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRow::AddInterfacesForISupportErrorInfo()
{
HRESULT hr = S_OK;
if( SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_IColumnsInfo)) &&
SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_IConvertType)) &&
SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_IGetSession)) &&
SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_IRowChange)) &&
SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_IScopedOperations)) &&
SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_IBindResource)))
{
hr = m_pISupportErrorInfo->AddInterfaceID(IID_IRow);
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// Function to the get the value of the columns requested
/////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRow::GetColumns(DBORDINAL cColumns,DBCOLUMNACCESS rgColumns[ ])
{
HRESULT hr = E_FAIL;
for( ULONG_PTR lIndex = 0 ; lIndex < cColumns ; lIndex++)
{
//=============================================
// Initialize the output memeber variables
//=============================================
rgColumns[lIndex].cbDataLen = 0;
rgColumns[lIndex].dwStatus = DBSTATUS_S_OK;
}
//======================================================
// if the row object is created by the rowset then
// get the data maintained by the rowset object
//======================================================
if(m_pSourcesRowset != NULL)
{
hr = GetColumnsFromRowset(cColumns,rgColumns);
}
else
{
/// Get data for the requested columns
hr = GetRowData(cColumns,rgColumns);
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// Function to the get the value of the columns when row object is created from rowset
/////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRow::GetColumnsFromRowset(DBORDINAL cColumns,DBCOLUMNACCESS rgColumns[])
{
DBORDINAL icol;
ROWBUFF *pRowBuff;
COLUMNDATA *pColumnData;
DBCOUNTITEM ulErrorCount = 0;
DBTYPE dwSrcType;
DBTYPE dwDstType;
void *pSrc;
void *pDst;
DBLENGTH ulSrcLength;
DBLENGTH *pulDstLength;
DBLENGTH ulDstMaxLength;
DBSTATUS dwSrcStatus;
DBSTATUS *pdwDstStatus;
HRESULT hr = S_OK;
DBSTATUS dwStatus = DBSTATUS_S_OK;
CDataMap dataMap;
BOOL bUseDataConvert = TRUE;
VARIANT varValue;
VariantInit(&varValue);
//=========================================================
// Check if the row is already deleted
//=========================================================
dwStatus = m_pSourcesRowset->GetRowStatus(m_hRow);
if( dwStatus != DBROWSTATUS_S_OK)
{
if(dwStatus == DBROWSTATUS_E_DELETED)
{
hr = DB_E_DELETEDROW;
}
else
{
hr = E_FAIL;
}
}
if( SUCCEEDED(hr))
{
//=========================================================
// if data is not yet received then fetch the data
//=========================================================
if(S_OK != m_pSourcesRowset->IsSlotSet(m_hRow))
{
hr = m_pSourcesRowset->GetData(m_hRow);
}
if(SUCCEEDED(hr))
{
if( (m_pSourcesRowset->m_ulProps & OTHERUPDATEDELETE) &&(m_pSourcesRowset->m_ulLastFetchedRow != m_hRow))
{
if(SUCCEEDED(hr = m_pSourcesRowset->GetDataToLocalBuffer(m_hRow)))
{
m_pSourcesRowset->m_ulLastFetchedRow = m_hRow;
}
}
if(SUCCEEDED(hr))
{
//=========================================================
// Get the pointer to the rowbuffer
//=========================================================
pRowBuff = m_pSourcesRowset->GetRowBuff(m_hRow , TRUE);
assert(pRowBuff != NULL);
// Navigate for each requested column
for( ULONG lIndex = 0 ; lIndex < cColumns ; lIndex++)
{
bUseDataConvert = TRUE;
// if the column is a bookmark then continue without doing anything
if(rgColumns[lIndex].columnid.eKind == DBKIND_GUID_PROPID &&
rgColumns[lIndex].columnid.uGuid.guid == DBCOL_SPECIALCOL &&
rgColumns[lIndex].columnid.uName.ulPropid >= 2)
{
if(m_pSourcesRowset->m_ulProps & BOOKMARKPROP)
{
dwSrcType = DBTYPE_I4;
pSrc = &pRowBuff->dwBmk;
ulSrcLength = pRowBuff->cbBmk;
dwSrcStatus = DBSTATUS_S_OK;
icol = 0;
}
else
{
continue;
}
}
else
{
//=================================================================
// If the columnID is not of type name then set the status
// to unavialable as only this is supported
//=================================================================
if(rgColumns[lIndex].columnid.eKind != DBKIND_NAME)
{
rgColumns[lIndex].dwStatus = DBSTATUS_E_UNAVAILABLE;
continue;
}
icol = m_pSourcesRowset->GetOrdinalFromColName(rgColumns[lIndex].columnid.uName.pwszName);
//=========================================================================================
// The column unavailable for the row as the class qualifier belongs to a parent rowset
//=========================================================================================
if(S_OK == (hr =m_pCreator->GetDataSrcProperty(DBPROP_WMIOLEDB_QUALIFIERS,varValue)))
if( (varValue.lVal & CLASS_QUALIFIERS) &&
m_bClassChanged &&
icol == 1 &&
m_pRowColumns->ColumnType(icol) == DBTYPE_HCHAPTER)
{
rgColumns[lIndex].dwStatus = DBSTATUS_E_UNAVAILABLE;
continue;
}
//=================================================================
// If the requested column is not part of the source rowset
// get it directly from the instance
//=================================================================
if((DB_LORDINAL) icol == -1)
{
hr = GetColumnData(rgColumns[lIndex]);
if ( hr != S_OK )
{
ulErrorCount++;
}
continue;
}
pColumnData = (COLUMNDATA *) ((BYTE *) pRowBuff + m_pSourcesRowset->m_Columns.GetDataOffset(icol));
dwSrcType = (SHORT)pColumnData->dwType;
if( dwSrcType == DBTYPE_BSTR)
{
pSrc = &(pColumnData->pbData);
}
else
{
pSrc = (pColumnData->pbData);
}
ulSrcLength = pColumnData->dwLength;
dwSrcStatus = pColumnData->dwStatus;
}
ulDstMaxLength = rgColumns[lIndex].cbMaxLen;
dwDstType = rgColumns[lIndex].wType;
pDst = rgColumns[lIndex].pData;
pulDstLength = &rgColumns[lIndex].cbDataLen;
pdwDstStatus = &rgColumns[lIndex].dwStatus;
//==========================================================
// if the column is of type chapter then consider that
// as a of type long as HCHAPTER is a ULONG value
//==========================================================
if(dwSrcType == DBTYPE_HCHAPTER)
{
dwSrcType = DBTYPE_UI4;
}
if(dwDstType == DBTYPE_HCHAPTER)
{
dwDstType = DBTYPE_UI4;
}
//=================================================================
// if both the source and destination type is array then don't
// use IDataConvert::DataConvert for conversion
//=================================================================
if( (dwSrcType & DBTYPE_ARRAY) && (dwDstType & DBTYPE_ARRAY) )
{
bUseDataConvert = FALSE;
}
if( dwSrcType != VT_NULL && dwSrcType != VT_EMPTY && bUseDataConvert == TRUE && pSrc != NULL)
{
// NTRaid:138957
// since for DBTYPE_UI4 the data returned from WMI
// is of type DBTYPE_I4 changing the source type does not
// have any effect except that the VARIANT type of the
// output will be VT_I4 instead of VT_UI4
DBTYPE dbSrcType = dwSrcType;
if(dwDstType == DBTYPE_VARIANT)
{
dbSrcType = GetVBCompatibleAutomationType(dwSrcType);
}
hr = g_pIDataConvert->DataConvert(
dbSrcType,
dwDstType,
ulSrcLength,
pulDstLength,
pSrc,
pDst,
ulDstMaxLength,
dwSrcStatus,
pdwDstStatus,
rgColumns[lIndex].bPrecision, // bPrecision for conversion to DBNUMERIC
rgColumns[lIndex].bScale, // bScale for conversion to DBNUMERIC
DBDATACONVERT_DEFAULT);
if(hr == DB_E_UNSUPPORTEDCONVERSION && pdwDstStatus != NULL)
{
*pdwDstStatus = DBSTATUS_E_CANTCONVERTVALUE;
}
}
else
if(bUseDataConvert == FALSE && pSrc != NULL)
{
//=================================================================
// Call this function to get the array in the destination address
//=================================================================
hr = dataMap.ConvertAndCopyArray((SAFEARRAY *)pSrc,(SAFEARRAY **)pDst, dwSrcType,dwDstType,pdwDstStatus);
if( *pdwDstStatus == DBSTATUS_E_CANTCONVERTVALUE)
{
*pulDstLength = 0;
}
}
else
{
*pulDstLength = 0;
*pdwDstStatus = DBSTATUS_S_ISNULL;
}
//===================================================================
// Ignoring the array for the time being
// to be removed later
//===================================================================
if(dwSrcType & VT_ARRAY)
{
hr = S_OK;
}
if (hr != S_OK )
{
ulErrorCount++; // can't coerce
hr = S_OK;
}
} // for loop
} // if succeeded(hr) after getting local buffer address
} // if Succeeded(hr) after getting the slot number
} // if Succeeded(hr) after initial checking
//===================================================================
// We report any lossy conversions with a special status.
// Note that DB_S_ERRORSOCCURED is a success, rather than failure.
//===================================================================
if ( SUCCEEDED(hr) )
{
hr = ( ulErrorCount ? DB_S_ERRORSOCCURRED : S_OK );
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// Function to update a row
/////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRow::UpdateRow(DBORDINAL cColumns,DBCOLUMNACCESS rgColumns[ ])
{
VARIANT varProp;
HRESULT hr = E_FAIL;
VariantInit(&varProp);
if(m_pSourcesRowset != NULL)
{
//===================================================================
// Check if updatibility is supported by the parent rowset
//===================================================================
if(SUCCEEDED(hr = m_pSourcesRowset->GetRowsetProperty(DBPROP_UPDATABILITY , varProp)))
{
//=========================================================
// If the rowset is not updatable then return failure
//=========================================================
if(!( varProp.lVal & DBPROPVAL_UP_CHANGE))
{
hr = E_FAIL;
}
else
{
hr = UpdateColumnsFromRowset(cColumns,rgColumns);
}
}
}
else
{
hr = SetRowData(cColumns,rgColumns);
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// Function to update a row when it is created by a rowset
/////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRow::UpdateColumnsFromRowset(DBORDINAL cColumns,DBCOLUMNACCESS rgColumns[ ])
{
DBORDINAL icol;
ROWBUFF *pRowBuff;
COLUMNDATA *pColumnData;
DBCOUNTITEM ulErrorCount = 0;
DBTYPE dwSrcType;
DBTYPE dwDstType;
void *pSrc;
void *pDst;
void *pTemp;
DBLENGTH ulSrcLength;
DBLENGTH ulDstLength;
DBLENGTH ulDstMaxLength;
DBSTATUS dwSrcStatus;
DBSTATUS dwDstStatus;
HRESULT hr = S_OK;
DBSTATUS dwStatus = DBSTATUS_S_OK;
CVARIANT cvarData;
VARIANT *pvarData = &cvarData;
CDataMap map;
ULONG lFlags = 0;
BOOL bUseDataConvert = TRUE;
DWORD dwCIMType = 0;
dwStatus = m_pSourcesRowset->GetRowStatus(m_hRow);
if( dwStatus != DBROWSTATUS_S_OK)
{
if(dwStatus == DBROWSTATUS_E_DELETED)
{
hr = DB_E_DELETEDROW;
}
else
{
hr = E_FAIL;
}
}
else
{
//========================================================
// if data is not yet received then fetch the data
//========================================================
if(S_OK != m_pSourcesRowset->IsSlotSet(m_hRow))
{
hr = m_pSourcesRowset->GetData(m_hRow);
}
if(SUCCEEDED(hr))
{
//========================================
// Get the pointer to the rowbuffer
//========================================
pRowBuff = m_pSourcesRowset->GetRowBuff(m_hRow , TRUE);
assert(pRowBuff != NULL);
for( ULONG lIndex = 0 ; lIndex < cColumns ; lIndex++)
{
bUseDataConvert = TRUE;
if(rgColumns[lIndex].columnid.eKind != DBKIND_NAME)
{
rgColumns[lIndex].dwStatus = DBSTATUS_E_UNAVAILABLE;
continue;
}
icol = m_pSourcesRowset->GetOrdinalFromColName(rgColumns[lIndex].columnid.uName.pwszName);
//===================================================================================
// If the requested column is not part of the source rowset
// call SetColumnData function to set it directly from the instance
//===================================================================================
if((DB_LORDINAL)icol < 0)
{
hr = SetColumnData(rgColumns[lIndex]);
if ( hr != S_OK )
{
ulErrorCount++;
}
continue;
}
pColumnData = (COLUMNDATA *) ((BYTE *) pRowBuff + m_pSourcesRowset->m_Columns.GetDataOffset(icol));
//==================================================
// check if the column is readonly or not
//==================================================
lFlags = m_pSourcesRowset->m_Columns.ColumnFlags(icol);
if((m_pSourcesRowset->m_Columns.ColumnFlags(icol) & DBCOLUMNFLAGS_WRITE) == 0)
{
pColumnData->dwStatus = DBSTATUS_E_READONLY;
ulErrorCount++;
continue;
}
dwSrcType = rgColumns[lIndex].wType;
ulSrcLength = rgColumns[lIndex].cbDataLen;
dwSrcStatus = rgColumns[lIndex].dwStatus;
pSrc = rgColumns[lIndex].pData;
ulDstMaxLength = -1;
dwDstType = (SHORT)pColumnData->dwType;
// pDst = &varData;
//==========================================================
// if the column is of type chapter then consider that
// as a of type long as HCHAPTER is a ULONG value
//==========================================================
if(dwSrcType == DBTYPE_HCHAPTER)
{
dwSrcType = DBTYPE_UI4;
}
if(dwDstType == DBTYPE_HCHAPTER)
{
dwDstType = DBTYPE_UI4;
}
hr = g_pIDataConvert->GetConversionSize(dwSrcType, dwDstType, &ulSrcLength, &ulDstLength, pSrc);
try
{
pDst = new BYTE[ulDstLength];
}
catch(...)
{
SAFE_DELETE_ARRAY(pDst);
throw;
}
//===================================================================================
// if both the source and destination type is array then don't
// use IDataConvert::DataConvert for conversion
//===================================================================================
if( (dwSrcType & DBTYPE_ARRAY) && (dwDstType & DBTYPE_ARRAY) )
{
bUseDataConvert = FALSE;
}
// this function is called to check for some non automation types
dwSrcType = GetVBCompatibleAutomationType(dwSrcType);
//===================================================================================
// If the source type is not array or empty or null the use the conversion library
// for converting the data
//===================================================================================
if( dwSrcType != VT_NULL && dwSrcType != VT_EMPTY && bUseDataConvert == TRUE && pSrc != NULL)
{
hr = g_pIDataConvert->DataConvert(
dwSrcType,
dwDstType,
ulSrcLength,
&ulDstLength,
pSrc,
pDst,
ulDstMaxLength,
dwSrcStatus,
&dwDstStatus,
0, // bPrecision for conversion to DBNUMERIC
0, // bScale for conversion to DBNUMERIC
DBDATACONVERT_DEFAULT);
if(hr == DB_E_UNSUPPORTEDCONVERSION )
{
dwDstStatus = DBSTATUS_E_CANTCONVERTVALUE;
}
}
else
if(bUseDataConvert == FALSE && pSrc != NULL)
{
//==================================================================
// Call this function to get the array in the destination address
//==================================================================
hr = map.ConvertAndCopyArray((SAFEARRAY *)pSrc,(SAFEARRAY **)pDst, dwSrcType,dwDstType, &dwDstStatus);
if(dwDstStatus == DBSTATUS_E_CANTCONVERTVALUE)
{
ulDstLength = 0;
ulErrorCount++;
}
}
else
{
pDst = NULL;
ulDstLength = 0;
dwDstStatus = DBSTATUS_S_ISNULL;
}
if( hr == S_OK)
{
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(pDst != NULL && pColumnData->dwType == VT_BSTR)
{
pTemp = *(BSTR **)pDst;
}
else
{
pTemp = pDst;
}
//====================================
// If data is is modified then
//====================================
if((map.CompareData(dwDstType,pColumnData->pbData,pTemp) == FALSE)
&& !( pColumnData->pbData == NULL && ulDstLength == 0))
{
//===============================
// Release the Old data
//===============================
pColumnData->ReleaseColumnData();
if(ulDstLength > 0)
{
//=====================================================================
// Convert the new data to Variant. This function return the status
// if not able to conver the data
//=====================================================================
hr = map.MapAndConvertOLEDBTypeToCIMType((USHORT)pColumnData->dwType,pTemp,ulDstLength,*pvarData,dwCIMType);
}
if( hr == S_OK)
{
hr = pColumnData->SetData(cvarData,dwDstType);
//==============================
// Set the data to modified
//==============================
pColumnData->dwStatus |= COLUMNSTAT_MODIFIED;
cvarData.Clear();
}
else
{
//==============================
// Set the data to modified
//==============================
pColumnData->dwStatus |= hr;
ulErrorCount++;
}
}
}
else
{
ulErrorCount++;
rgColumns[lIndex].dwStatus = dwDstStatus;
}
SAFE_DELETE_ARRAY(pDst);
} // for loop
//===============================================================
// if the error count is less than the number of columns
// then there is atleast one column to be updated
//===============================================================
if( ulErrorCount < cColumns)
{
//====================================================================
// Update the the row
//====================================================================
hr = m_pSourcesRowset->UpdateRowData(m_hRow,cColumns,rgColumns);
}
//===================================================================
// We report any lossy conversions with a special status.
// Note that DB_S_ERRORSOCCURED is a success, rather than failure.
//===================================================================
if ( SUCCEEDED(hr) )
{
hr = ( ulErrorCount ? DB_S_ERRORSOCCURRED : S_OK );
}
}
} // else of check if deleted
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// Virtual overridden function which is called from IColumnInfo to get the column information
/////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRow::GetColumnInfo(DBORDINAL* pcColumns, DBCOLUMNINFO** prgInfo,WCHAR** ppStringsBuffer)
{
DBORDINAL icol = 0;
DBCOLUMNINFO* rgdbcolinfo = NULL;
WCHAR* pstrBuffer = NULL;
WCHAR* pstrBufferForColInfo = NULL;
HRESULT hr = S_OK;
ptrdiff_t dp;
DBCOUNTITEM cSourcesCol = 0;
if(SUCCEEDED(hr = m_pRowColumns->CopyColumnInfoList(rgdbcolinfo,(m_pSourcesRowset != NULL))))
{
//=========================================================================
// Copy the heap for column names.
//=========================================================================
if (m_pSourcesRowset != NULL && m_pRowColumns->ColumnNameListStartingPointOfSrcRs() != NULL){
hr = m_pRowColumns->CopyColumnNamesList(pstrBuffer);
if( hr != S_OK || pstrBuffer == NULL)
{
hr = E_OUTOFMEMORY;
}
else
{
//==================================================================================
// This will give the starting pointer difference to the columns names of the
// source rowset
//==================================================================================
dp = (LONG_PTR) pstrBuffer - (LONG_PTR) (m_pRowColumns->ColumnNameListStartingPointOfSrcRs());
dp >>= 1;
//=========================================================================
// Loop through columns and adjust pointers
// to column names.
//=========================================================================
cSourcesCol = m_pRowColumns->GetNumberOfColumnsInSourceRowset();
for ( icol =0; icol < cSourcesCol; icol++ )
{
if ( rgdbcolinfo[icol].pwszName )
{
rgdbcolinfo[icol].pwszName += dp;
}
if(rgdbcolinfo[icol].wType == DBTYPE_HCHAPTER)
{
rgdbcolinfo[icol].dwFlags = DBCOLUMNFLAGS_ISCOLLECTION | DBCOLUMNFLAGS_ISCHAPTER ;
}
}
//==================================================================================================================
// This will give the starting pointer difference to the columns names of the columns which is not present in the
// sources rowset
// Here the number of bytes copied for source rowset column names has to be taken care of
//==================================================================================================================
dp = (LONG_PTR) pstrBuffer + m_pRowColumns->GetCountOfBytesCopiedForSrcRs() - (LONG_PTR) (m_pRowColumns->ColumnNameListStartingPoint());
dp >>= 1;
}
}
else
{
if( SUCCEEDED(hr = m_pRowColumns->CopyColumnNamesList(pstrBuffer)))
{
//================================================================================
// This will give the starting pointer difference to the columns names of the
// source rowset
//================================================================================
dp = (LONG_PTR) pstrBuffer - (LONG_PTR) (m_pRowColumns->ColumnNameListStartingPoint());
dp >>= 1;
icol = 0;
}
}
if(SUCCEEDED(hr))
{
//===========================================
// Loop through columns and adjust pointers
// to column names.
//===========================================
for ( ; icol < m_cTotalCols ; icol++ )
{
if ( rgdbcolinfo[icol].pwszName )
{
rgdbcolinfo[icol].pwszName += dp;
}
}
//=======================================================
// If the row's column is of type HCHAPTER change it
// to empty and the flag to DBCOLUMNFLAGS_ISCOLLECTION
//=======================================================
if(m_cNestedCols > 0)
for(icol = 0; icol < m_cTotalCols ; icol++)
{
if(rgdbcolinfo[icol].wType == DBTYPE_HCHAPTER)
{
rgdbcolinfo[icol].wType = DBTYPE_HCHAPTER;
rgdbcolinfo[icol].dwFlags = DBCOLUMNFLAGS_ISCHAPTER | DBCOLUMNFLAGS_ISCOLLECTION;
rgdbcolinfo[icol].ulColumnSize = sizeof(DBLENGTH);
}
}
//===================================================================================================
// Setting the output parameters
//===================================================================================================
*prgInfo = &rgdbcolinfo[0];
*ppStringsBuffer = pstrBuffer;
*pcColumns = m_cTotalCols;
} // if succeeded(hr)
} // if succeeded(CopyColumnInfoList())
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// Function to get the column information of the row. THis function check if the class name of the
// rowset which created the row belongs to the same class as that of the instance pointing the current row
// If these two are different , this ffunction get the col info for this row
/////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRow::GetRowColumnInfo()
{
WCHAR *pstrRsClassName = NULL, *pstrRowClassName = NULL;
HRESULT hr = S_OK;
//====================================================
// Get the class name to which the instance belongs
//====================================================
pstrRowClassName = m_pInstance->GetClassName();
if( pstrRowClassName != NULL)
{
//================================================
// Get the class name of the source rowset
//================================================
pstrRsClassName = m_pSourcesRowset->m_pMap->GetClassName();
}
//============================================================
// Set the bClassChanged flag to true if instance points to
// different class than that of the source rowset
//============================================================
if( pstrRsClassName == NULL && pstrRowClassName == NULL)
{
m_bClassChanged = FALSE;
}
else
if( pstrRsClassName == NULL || pstrRowClassName == NULL)
{
m_bClassChanged = TRUE;
}
else
if(_wcsicmp(pstrRsClassName,pstrRowClassName) != 0)
{
m_bClassChanged = TRUE;
}
//=====================================================================
// If the source rowset and the row points to different classes ,
// then the columnd info of the remaining columns has to be obtained
//=====================================================================
if(m_bClassChanged == TRUE)
{
//===========================================
// Get the flags of the source rowset
//===========================================
DWORD dwFlags = m_pInstance->GetFlags();
SAFE_RELEASE_PTR(m_pMap);
//===================================
// Create a new map class
//===================================
m_pMap = new CWmiOleDBMap;
if(m_pMap == NULL)
{
hr = E_OUTOFMEMORY;
}
else
{
if(SUCCEEDED(hr = m_pMap->FInit(dwFlags,pstrRowClassName,
m_pCon == NULL ?m_pCreator->m_pCDataSource->m_pWbemWrap: m_pCon)))
{
m_pMap->AddRef();
//============================
// Get the column info
//============================
hr = GetColumnInfo();
}
}
}
SAFE_DELETE_ARRAY(pstrRowClassName);
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// Get the number of columns in the row and allocate memory
/////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRow::GetColumnInfo()
{
HRESULT hr = S_OK;
VARIANT varValue;
VariantInit(&varValue);
// Bug which not able to get system properties from Row object
// NTRaid: 140657
// 05/06/00
//===========================================================================================
// Get the DataSource property to check if system Properties is to be fetched?
//===========================================================================================
if(SUCCEEDED(hr = m_pCreator->GetDataSrcProperty(DBPROP_WMIOLEDB_SYSTEMPROPERTIES,varValue)))
{
if( varValue.boolVal == VARIANT_TRUE)
{
m_pMap->SetSytemPropertiesFlag(TRUE);
}
//==================================================================================
// switch on type of the qualifier. If it is 0 then the recordset is
// representing the instances of the class
//==================================================================================
switch( m_uRsType)
{
case 0 :
//==================================================================================
// Get the count of columns in the table
//==================================================================================
hr = m_pMap->GetColumnCount(m_cTotalCols,m_cCols,m_cNestedCols);
// If source rowset is present and
// If the property for showing system property is false and
// if the source rowset is created by a query of mixed type
// ( meaning rowset created executing a query, which results
// in heterogenous objects ) then add another column to the row
// which is part of the source rowset to show __PATH
// NTRaid : 142133 & 141923
// 07/12/00
if(m_pSourcesRowset != NULL && m_cTotalCols)
{
if( varValue.boolVal == FALSE)
{
// all types of rowset has to have an extr column as __PATH property
// which is a system property is shown in the row even if the
// DBPROP_WMIOLEDB_SYSTEMPROPERTIES is set to FALSE
if(NORMAL != m_pSourcesRowset->GetObjListType())
{
m_cTotalCols++;
m_cCols++;
}
}
VariantClear(&varValue);
}
break;
case PROPERTYQUALIFIER :
case CLASSQUALIFIER:
//==================================================================================
// Get the number of columns for the property qualifier
//==================================================================================
m_cCols = NUMBER_OF_COLUMNS_IN_QUALIFERROWSET + 1; // for bookmarkcolumn
m_cTotalCols = m_cCols;
break;
};
}
if( SUCCEEDED(hr))
{
// The column unavailable for the row as the class qualifier belongs to a parent rowset
if(m_pSourcesRowset != NULL && S_OK == (hr =m_pCreator->GetDataSrcProperty(DBPROP_WMIOLEDB_QUALIFIERS,varValue)))
if( (varValue.lVal & CLASS_QUALIFIERS) &&
m_bClassChanged)
{
m_cTotalCols++; // This is to accomodate another column which actually
// holds the class/instance qualifiers
}
if( S_OK == (hr = m_pRowColumns->AllocColumnNameList(m_cTotalCols))){
//===============================================================================
// Allocate the DBCOLUMNINFO structs to match the number of columns
//===============================================================================
if( S_OK == (hr = m_pRowColumns->AllocColumnInfoList(m_cTotalCols))){
hr = GatherColumnInfo();
}
}
}
//==================================================================================
// Free the columnlist if more is allocated
//==================================================================================
if( hr != S_OK ){
m_pRowColumns->FreeColumnNameList();
m_pRowColumns->FreeColumnInfoList();
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// Get the col info for row
/////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRow::GatherColumnInfo()
{
HRESULT hr = S_OK;
switch( m_uRsType)
{
case 0 :
//=============================================================
// Get Column Names and Lengths
//=============================================================
hr = m_pMap->GetColumnInfoForParentColumns(m_pRowColumns);
break;
case PROPERTYQUALIFIER:
//==================================================================================
// Get the number of columns for the property qualifier
//==================================================================================
hr = CBaseRowObj::GatherColumnInfoForQualifierRowset();
break;
case CLASSQUALIFIER:
break;
};
if(SUCCEEDED(hr))
{
m_cbRowSize = m_pRowColumns->SetRowSize();
hr = m_pRowColumns->FreeUnusedMemory();
}
return hr;
}
//////////////////////////////////////////////////////////////////////////////////////
// Get data for a particular column
//////////////////////////////////////////////////////////////////////////////////////
HRESULT CRow::GetColumnData(DBCOLUMNACCESS &col)
{
DBORDINAL icol = 0;
DBCOUNTITEM ulErrorCount = 0;
CIMTYPE cimType = 0;
DBTYPE dwSrcType;
DBTYPE dwDstType;
void *pSrc = NULL;
void *pDst = NULL;
BYTE *pTemp = NULL;
DBLENGTH ulSrcLength;
DBLENGTH *pulDstLength = NULL;
DBLENGTH ulDstMaxLength = NULL;
DBSTATUS dwSrcStatus = 0;
DBSTATUS *pdwDstStatus = NULL;
HRESULT hr = S_OK;
DBSTATUS dwStatus = DBSTATUS_S_OK;
BSTR strProp = NULL;
DWORD dwFlags = 0;
CDataMap map;
BOOL bUseDataConvert = TRUE;
DBORDINAL lCollectionColData = 0;
icol = m_pRowColumns->GetColOrdinal(col.columnid.uName.pwszName);
if( icol > 0)
{
// If the column is of type HCHAPTER or if it is a collection ( meaning
// if the column represents any of the child rowsets) then set the
// column to ordinal of the column
if(m_pRowColumns->ColumnType(icol) == DBTYPE_HCHAPTER ||
m_pRowColumns->ColumnFlags(icol) & DBCOLUMNFLAGS_ISCOLLECTION ||
m_pRowColumns->ColumnFlags(icol) & DBCOLUMNFLAGS_ISCHAPTER)
{
col.bPrecision = 0;
col.bScale = 0;
lCollectionColData = icol;
dwSrcType = DBTYPE_UI4;
ulDstMaxLength = col.cbMaxLen;
dwDstType = (DBTYPE)col.wType;
pulDstLength = &col.cbDataLen;
pdwDstStatus = &col.dwStatus;
ulSrcLength = sizeof(lCollectionColData);
dwSrcStatus = DBSTATUS_S_OK;
pSrc = &lCollectionColData;
hr = S_OK;
}
else
{
strProp = Wmioledb_SysAllocString(col.columnid.uName.pwszName);
hr = m_pMap->GetProperty(m_pInstance,strProp, pTemp,dwSrcType ,ulSrcLength, dwFlags );
if(SUCCEEDED(hr))
{
// dwSrcType = (DBTYPE)cimType;
//==========================================
// check if the column is readonly or not
//==========================================
if((dwFlags & DBCOLUMNFLAGS_WRITE) == 0)
{
col.dwStatus = DBSTATUS_E_READONLY;
}
//=========================================================
// if the data is null set the status to null and return
//=========================================================
if(pTemp == NULL)
{
col.dwStatus = DBSTATUS_S_ISNULL;
hr = S_OK;
}
else
{
if( dwSrcType == DBTYPE_BSTR)
{
pSrc = &pTemp;
}
else
{
pSrc = pTemp;
}
ulDstMaxLength = col.cbMaxLen;
dwDstType = (DBTYPE)col.wType;
pulDstLength = &col.cbDataLen;
pdwDstStatus = &col.dwStatus;
}
}
SAFE_FREE_SYSSTRING(strProp);
}
if(SUCCEEDED(hr))
{
//==========================================================
// if the column is of type chapter then consider that
// as a of type long as HCHAPTER is a ULONG value
//==========================================================
if(dwSrcType == DBTYPE_HCHAPTER)
{
dwSrcType = DBTYPE_UI4;
}
if(dwDstType == DBTYPE_HCHAPTER)
{
dwDstType = DBTYPE_UI4;
}
pDst = (BYTE *)col.pData;
// if both the source and destination type is array then don't
// use IDataConvert::DataConvert for conversion
// Arrays are requested as VARIANTS then also do conversion using our conversion routine
// and fill the variant
if( (dwSrcType & DBTYPE_ARRAY) && ( (dwDstType & DBTYPE_ARRAY) || dwDstType == VT_VARIANT) )
{
bUseDataConvert = FALSE;
}
// this function is called to check for some non automation types
dwSrcType = GetVBCompatibleAutomationType(dwSrcType);
// this function is called to check for some non automation types
dwDstType = GetVBCompatibleAutomationType(dwDstType);
// If the source type is not array or empty or null the use the conversion library
// for converting the data
if( dwSrcType != VT_NULL && dwSrcType != VT_EMPTY && bUseDataConvert == TRUE && pSrc != NULL)
{
hr = g_pIDataConvert->DataConvert(
(USHORT)dwSrcType,
dwDstType,
ulSrcLength,
pulDstLength,
pSrc,
pDst,
ulDstMaxLength,
dwSrcStatus,
pdwDstStatus,
0, // bPrecision for conversion to DBNUMERIC
0, // bScale for conversion to DBNUMERIC
DBDATACONVERT_DEFAULT);
if(hr == DB_E_UNSUPPORTEDCONVERSION && pdwDstStatus != NULL)
{
*pdwDstStatus = DBSTATUS_E_CANTCONVERTVALUE;
}
if ( hr != S_OK)
{
ulErrorCount++;
}
}
else
if(bUseDataConvert == FALSE && pSrc != NULL)
{
SAFEARRAY *pArray = NULL;
SAFEARRAY **pTemp = NULL;
if(pDst != NULL)
{
pTemp = (SAFEARRAY **)pDst;
if(dwDstType == VT_VARIANT)
{
pTemp = &pArray;
}
}
// Call this function to get the array in the destination address
hr = map.ConvertAndCopyArray((SAFEARRAY *)pSrc,pTemp, dwSrcType,dwDstType,pdwDstStatus);
if( *pdwDstStatus == DBSTATUS_E_CANTCONVERTVALUE)
{
pulDstLength = 0;
}
if(SUCCEEDED(hr) && dwDstType == VT_VARIANT)
{
VariantInit((VARIANT *)pDst);
if(pArray && pDst != NULL)
{
((VARIANT *)pDst)->vt = VT_ARRAY | VT_VARIANT;
((VARIANT *)pDst)->parray = pArray;
}
}
}
else
{
if(pulDstLength)
{
*pulDstLength = 0;
}
if(pdwDstStatus)
{
*pdwDstStatus = DBSTATUS_S_ISNULL;
}
}
//===============================
// Free the data allocated
//===============================
map.FreeData(dwSrcType , pTemp);
}
}
else
{
col.dwStatus = DBSTATUS_E_UNAVAILABLE;
hr = E_FAIL;
}
return hr;
}
//////////////////////////////////////////////////////////////////////////////////////
// Set a value of a particular column
//////////////////////////////////////////////////////////////////////////////////////
HRESULT CRow::SetColumnData(DBCOLUMNACCESS &col,BOOL bNewRow)
{
DBORDINAL icol;
DBCOUNTITEM ulErrorCount = 0;
DBTYPE dwSrcType;
DBTYPE dwDstType;
void *pSrc = NULL;
void *pDst = NULL;
void *pTemp = NULL;
DBLENGTH lSrcLength;
DBLENGTH lDstLength;
DBLENGTH lDstMaxLength;
DBSTATUS dwSrcStatus;
DBSTATUS dwDstStatus;
HRESULT hr = S_OK;
CVARIANT cvarData;
VARIANT *pvarData = &cvarData;
CDataMap map;
ULONG lFlags = 0;
BSTR strProp;
BOOL bUseDataConvert = TRUE;
DWORD dwCIMType = 0;
//===============================================================
// Get the ordinal of the column from the column information
//===============================================================
icol = m_pRowColumns->GetColOrdinal(col.columnid.uName.pwszName);
if( ((LONG)icol) >= 0)
{
strProp = Wmioledb_SysAllocString(col.columnid.uName.pwszName);
//================================================
// check if the column is readonly or not
// If it is a new row continue updating
//================================================
lFlags = m_pRowColumns->ColumnFlags(icol);
if(((bNewRow == FALSE) && ((m_pRowColumns->ColumnFlags(icol) & DBCOLUMNFLAGS_WRITE) == 0)) ||
((bNewRow == TRUE) && m_pMap->IsSystemProperty(strProp)))
{
col.dwStatus = DBSTATUS_E_READONLY;
ulErrorCount++;
hr = DB_S_ERRORSOCCURRED;
}
else
{
dwSrcType = col.wType;
lSrcLength = col.cbDataLen;
dwSrcStatus = col.dwStatus;
if(dwSrcType == DBTYPE_BSTR)
{
pSrc = &col.pData;
}
else
{
pSrc = col.pData;
}
lDstMaxLength = -1;
dwDstType = (SHORT)m_pRowColumns->ColumnType(icol);
//==========================================================
// if the column is of type chapter then consider that
// as a of type long as HCHAPTER is a ULONG value
//==========================================================
if(dwSrcType == DBTYPE_HCHAPTER)
{
dwSrcType = DBTYPE_UI4;
}
if(dwDstType == DBTYPE_HCHAPTER)
{
dwDstType = DBTYPE_UI4;
}
hr = g_pIDataConvert->GetConversionSize(dwSrcType, dwDstType, &lSrcLength, &lDstLength, pSrc);
try
{
pDst = new BYTE[lDstLength];
}
catch(...)
{
SAFE_DELETE_ARRAY(pDst);
throw;
}
// if both the source and destination type is array then don't
// use IDataConvert::DataConvert for conversion
if((dwSrcType & DBTYPE_ARRAY) && (dwDstType & DBTYPE_ARRAY))
{
bUseDataConvert = FALSE;
}
// this function is called to check for some non automation types
dwSrcType = GetVBCompatibleAutomationType(dwSrcType);
// If the source type is not array or empty or null the use the conversion library
// for converting the data
if( dwSrcType != VT_NULL && dwSrcType != VT_EMPTY && bUseDataConvert == TRUE && pSrc != NULL)
{
hr = g_pIDataConvert->DataConvert(
dwSrcType,
dwDstType,
lSrcLength,
&lDstLength,
pSrc,
pDst,
lDstMaxLength,
dwSrcStatus,
&dwDstStatus,
0, // bPrecision for conversion to DBNUMERIC
0, // bScale for conversion to DBNUMERIC
DBDATACONVERT_DEFAULT);
if(hr == DB_E_UNSUPPORTEDCONVERSION )
{
dwDstStatus = DBSTATUS_E_CANTCONVERTVALUE;
}
}
else
if(bUseDataConvert == FALSE && pSrc != NULL)
{
// Call this function to get the array in the destination address
hr = map.ConvertAndCopyArray((SAFEARRAY *)pSrc,(SAFEARRAY **)pDst, dwSrcType,dwDstType,&dwDstStatus);
if( dwDstStatus == DBSTATUS_E_CANTCONVERTVALUE)
{
lDstLength = 0;
}
}
else
{
lDstLength = 0;
dwDstStatus = DBSTATUS_S_ISNULL;
}
if(SUCCEEDED(hr))
{
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(dwDstType & DBTYPE_ARRAY)
{
dwCIMType = m_Columns.GetCIMType(icol);
}
if(pDst != NULL && dwDstType == VT_BSTR)
{
pTemp = *(BSTR **)pDst;
}
else
{
pTemp = pDst;
}
//=========================================
// If data is is modified then
//=========================================
if( pTemp != NULL && lDstLength != 0)
{
if(lDstLength > 0)
{
//===========================================
// Convert the new data to Variant
//===========================================
map.MapAndConvertOLEDBTypeToCIMType((USHORT)dwDstType,pTemp,lDstLength,*pvarData,dwCIMType);
hr = m_pInstance->SetProperty(strProp,pvarData);
}
cvarData.Clear();
}
}
else
{
ulErrorCount++;
col.dwStatus = dwDstStatus;
}
SAFE_DELETE_PTR(pDst);
}
SysFreeString(strProp);
}
//===================================================================
// We report any lossy conversions with a special status.
// Note that DB_S_ERRORSOCCURED is a success, rather than failure.
//===================================================================
if ( SUCCEEDED(hr) )
{
hr = ( ulErrorCount ? DB_S_ERRORSOCCURRED : S_OK );
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// Get the rowdata and put it into the buffer pointed by the second parameter
/////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRow::GetRowData(DBORDINAL cColumns,DBCOLUMNACCESS rgColumns[])
{
ULONG ulErrorCount = 0;
HRESULT hr = S_OK;
//=========================================================
// Navigate through every element in the array, get
// the value of the columns
//=========================================================
for (ULONG_PTR lIndex = 0 ; lIndex < cColumns ; lIndex++)
{
hr = GetColumnData(rgColumns[lIndex]);
if ( hr != S_OK )
{
ulErrorCount++;
hr = S_OK;
}
}
if ( SUCCEEDED(hr) )
{
hr = ( ulErrorCount ? DB_S_ERRORSOCCURRED : S_OK );
}
if( ulErrorCount >= cColumns)
{
hr = E_FAIL;
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// Set the the values of the different columns. This is called when row is created directly
// and not from rowset
/////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRow::SetRowData(DBORDINAL cColumns,DBCOLUMNACCESS rgColumns[])
{
ULONG ulErrorCount = 0;
HRESULT hr = S_OK;
//=========================================================
// Navigate through every element in the array, set
// the value of the columns
//=========================================================
for (ULONG_PTR lIndex = 0 ; lIndex < cColumns ; lIndex++)
{
hr = SetColumnData(rgColumns[lIndex]);
if ( hr != S_OK )
{
ulErrorCount++;
hr = S_OK;
}
}
if(SUCCEEDED(hr))
{
//==============================================
// call this function to update the instance
//==============================================
hr = m_pMap->UpdateInstance(m_pInstance,FALSE);
}
if ( SUCCEEDED(hr) )
{
hr = ( ulErrorCount ? DB_S_ERRORSOCCURRED : S_OK );
}
if( ulErrorCount >= cColumns)
{
hr = E_FAIL;
}
return hr;
}
//////////////////////////////////////////////////////////////////////////////////////
// Open a rowset on a column which represents qualifiers or embeded classes
// NTRaid:111833
// 06/07/00
//////////////////////////////////////////////////////////////////////////////////////
HRESULT CRow::OpenChild(IUnknown *pUnkOuter,WCHAR *strColName ,REFIID riid, IUnknown **ppUnk,BOOL bIsChildRowset)
{
HRESULT hr = S_OK;
ULONG cPropSets = 1;
// NTRaid:111833
// 06/13/00
DBPROPSET* prgPropertySets = NULL;
DBPROPIDSET rgPropIDSet[1];
VARIANT varValue;
VariantInit(&varValue);
rgPropIDSet[0].cPropertyIDs = 0;
rgPropIDSet[0].guidPropertySet = DBPROPSET_ROWSET;
//==============================================================================
// Get the properties set thru IDBBinderProperties
//==============================================================================
if(SUCCEEDED(hr = m_pUtilProp->GetProperties(PROPSET_ROWSET,0,rgPropIDSet, &cPropSets,&prgPropertySets)))
{
//==============================================================================
// If the column refers to a rowset ( pointing to a qualifier) get the rowset
//==============================================================================
if(bIsChildRowset)
{
hr = GetChildRowet(pUnkOuter,strColName ,prgPropertySets,cPropSets,riid,ppUnk);
}
//======================
// else get a row
//======================
else
{
hr = GetChildRow(pUnkOuter,strColName ,prgPropertySets,cPropSets,riid,ppUnk);
}
}
//==========================================================================
// Free memory we allocated to by GetProperties
//==========================================================================
m_pUtilProp->m_PropMemMgr.FreeDBPROPSET( cPropSets, prgPropertySets);
return hr;
}
///////////////////////////////////////////////////////////////
// Function to parse the column name to get the property name
// The returned pointer is to released by the caller
///////////////////////////////////////////////////////////////
WCHAR * CRow::GetPropertyNameFromColName(WCHAR *pColName)
{
WCHAR *pQualiferSuffix = NULL;
WCHAR *pPropName = NULL;
try
{
pQualiferSuffix = new WCHAR[wcslen(SEPARATOR) + wcslen(QUALIFIER_) + 1];
}
catch(...)
{
SAFE_DELETE_ARRAY(pQualiferSuffix);
throw;
}
if(pQualiferSuffix)
{
swprintf(pQualiferSuffix,L"%s%s",SEPARATOR,QUALIFIER_);
if( wcsstr(pColName,pQualiferSuffix))
{
int nPropLen = wcslen(pColName) - wcslen(pQualiferSuffix) +1;
pPropName = new WCHAR [nPropLen];
//NTRaid:111767 & NTRaid:111768
// 06/07/00
if(pPropName)
{
memset(pPropName,0,nPropLen * sizeof(WCHAR));
memcpy(pPropName,pColName , (nPropLen-1) * sizeof(WCHAR));
}
}
SAFE_DELETE_ARRAY(pQualiferSuffix);
}
return pPropName;
}
//////////////////////////////////////////////////////////////////////////////////////
// Function which get the embeded instance given the URL of the instance
//////////////////////////////////////////////////////////////////////////////////////
HRESULT CRow::GetEmbededInstancePtrAndSetMapClass(CURLParser *urlParser)
{
BSTR strPath;
BSTR strProperty;
int nIndex = 0;
DWORD dwFlags = 0;
WCHAR * strTableName;
HRESULT hr = S_OK;
urlParser->GetPath(strPath);
urlParser->GetEmbededInstInfo(strProperty,nIndex);
m_pInstance = (CWbemClassInstanceWrapper *)m_pMap->GetEmbededInstance(strPath,strProperty,nIndex);
if( m_pInstance == NULL)
{
hr = E_FAIL;
}
else
{
//==================================================
// Set the class name of the wmioledbmap function
//==================================================
strTableName = m_pInstance->GetClassName();
hr = m_pMap->SetClass(strTableName);
delete [] strTableName;
SysFreeString(strPath);
SysFreeString(strProperty);
}
return hr;
}
//////////////////////////////////////////////////////////////////////////////////////
// Function to get a child row of the particular row which is pointed by a particular
// column
//////////////////////////////////////////////////////////////////////////////////////
HRESULT CRow::GetChildRow( IUnknown *pUnkOuter,
WCHAR *strColName,
DBPROPSET *prgPropertySets,
ULONG cPropSets,
REFIID riid,
IUnknown **ppUnk)
{
HRESULT hr = S_OK;
BSTR strPath,strTable , strURL;
CURLParser urlParser;
DBCOLUMNACCESS col;
CRow *pChildRow = NULL;
memset(&col,0,sizeof(DBCOLUMNACCESS));
col.pData = &strURL;
col.columnid.eKind = DBKIND_NAME;
col.columnid.uName.pwszName = strColName; ;
col.wType = DBTYPE_BSTR;
if(SUCCEEDED(hr = GetColumnData(col)))
{
urlParser.SetURL(strURL);
urlParser.GetClassName(strTable);
hr = urlParser.GetPathWithEmbededInstInfo(strPath);
try
{
pChildRow = new CRow(pUnkOuter, m_pCreator);
}
catch(...)
{
SAFE_DELETE_PTR(pChildRow);
throw;
}
if(SUCCEEDED(hr) && SUCCEEDED(hr = pChildRow->InitRow(strPath, strTable)))
{
hr = pChildRow->QueryInterface(riid, (void **)ppUnk);
}
SysFreeString(strTable);
SysFreeString(strPath);
}
if(FAILED(hr))
{
SAFE_DELETE_PTR(pChildRow);
}
return hr;
}
//////////////////////////////////////////////////////////////////////////////////////
// Function to get a child rowset of the particular row which is pointed by a particular
// column
//////////////////////////////////////////////////////////////////////////////////////
HRESULT CRow::GetChildRowet(IUnknown *pUnkOuter,
WCHAR *strColName,
DBPROPSET *prgPropertySets,
ULONG cPropSets,
REFIID riid,
IUnknown **ppUnk)
{
HRESULT hr = S_OK;
CRowset *pChildRowset = NULL;
int iOrdinal = 0;
WCHAR *pPropName = NULL;
ULONG lRsType = 0;
lRsType = m_pMap->ParseQualifiedNameToGetColumnType(strColName);
if(lRsType == WMI_PROPERTY_QUALIFIER)
{
//=============================================================
// Get the name of the property for which the qualifiers are
// to be retrieved as rowset
//=============================================================
pPropName = GetPropertyNameFromColName(strColName);
lRsType = PROPERTYQUALIFIER;
}
else
if(lRsType == WMI_CLASS_QUALIFIER)
{
lRsType = CLASSQUALIFIER;
}
if((pPropName != NULL && lRsType == PROPERTYQUALIFIER) ||
lRsType == CLASSQUALIFIER)
{
try
{
//================================
// Create a new rowset
//================================
pChildRowset = new CRowset(pUnkOuter,lRsType, pPropName,m_pCreator,m_pMap);
}
catch(...)
{
SAFE_DELETE_PTR(pChildRowset);
throw;
}
// Initialize the rowset
if( pChildRowset)
if(S_OK == (hr = pChildRowset->InitRowsetForRow(pUnkOuter,cPropSets,prgPropertySets,m_pInstance)))
{
hr = pChildRowset->QueryInterface(riid , (void **)ppUnk);
}
SAFE_DELETE_ARRAY(pPropName);
}
else
{
hr = DB_E_BADCOLUMNID;
}
return hr;
}
////////////////////////////////////////////////////////////////////////////////////////
// Creates a new instance
// called from ICreateRow::CreateRow
////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRow::CreateNewRow(CWbemClassInstanceWrapper **pNewInst)
{
return m_pMap->AddNewInstance((CWbemClassWrapper **)pNewInst);
}
////////////////////////////////////////////////////////////////////////////////////////
// Function which gets all the key values from the URL and updates it to
// the new instance
////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRow::UpdateKeysForNewInstance()
{
HRESULT hr = S_OK;
DBCOLUMNACCESS dbCol;
SAFEARRAY *psaKeyPropNames;
LONG lBound = 0 , uBound = 0;
BSTR strProperty;
LONG rgIndices[1];
CURLParser urlParser;
VARIANT varKeyValue;
CWbemClassWrapper * pTempInstance = NULL;
VariantInit(&varKeyValue);
urlParser.SetPath(m_strKey);
memset(&dbCol,0,sizeof(DBCOLUMNACCESS));
dbCol.columnid.eKind = DBKIND_NAME;
dbCol.columnid.uName.pwszName = NULL;
dbCol.cbDataLen = -1;
dbCol.wType = DBTYPE_VARIANT | DBTYPE_BYREF;
// Get the propertynames of the key values
hr = m_pMap->GetKeyPropertyNames(&psaKeyPropNames);
// Get the bounds of the array returned
hr = SafeArrayGetLBound(psaKeyPropNames,1,&lBound);
hr = SafeArrayGetUBound(psaKeyPropNames,1,&uBound);
// Navigate thru every element of the array
for( int nIndex = lBound ; nIndex <= uBound ; nIndex++)
{
rgIndices[0] = nIndex;
hr = SafeArrayGetElement(psaKeyPropNames,&rgIndices[0],(void *)&strProperty);
// Get the value of the key from the URL
if(SUCCEEDED(hr = urlParser.GetKeyValue(strProperty,varKeyValue)))
{
dbCol.columnid.uName.pwszName = (WCHAR *)strProperty;
dbCol.pData = &varKeyValue;
hr = SetColumnData(dbCol,TRUE);
VariantClear(&varKeyValue);
if(hr != S_OK)
{
break;
}
}
}
// Destroy the array created
SafeArrayDestroy(psaKeyPropNames);
if(SUCCEEDED(hr))
{
// call this function to save the new instance
hr = m_pMap->UpdateInstance(m_pInstance,TRUE);
}
// The instance may be created, but we have to
// check if the URL passed identifies the row , if no
// then return error
if( hr == S_OK)
{
// Convert it into upper case
pTempInstance = m_pMap->GetInstance(m_strKey);
if(pTempInstance == NULL)
{
hr = DB_E_NOTFOUND;
}
else
{
m_pInstance = (CWbemClassInstanceWrapper *)pTempInstance;
}
}
// Delete the instance created if there
// any failure in the process of creating new instance
if(FAILED(hr))
{
m_pMap->DeleteInstance(m_pInstance);
m_pInstance = NULL;
hr = DB_E_NOTFOUND;
}
return hr;
}
////////////////////////////////////////////////////////////////////////////////////////
// Function to open a row pointed by the URL
////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRow::OpenRow(LPCOLESTR pwszURL,IUnknown * pUnkOuter,REFIID riid,IUnknown** ppOut)
{
HRESULT hr = S_OK;
LONG lObjType = -1;
CRow * pRow = NULL;
CURLParser urlParser;
CBSTR bstrTemp;
CBSTR bstrPath;
CBSTR bstrClassName;
bstrTemp.SetStr((LPWSTR)pwszURL);
urlParser.SetURL((BSTR)bstrTemp);
lObjType = urlParser.GetURLType();
switch(lObjType)
{
case URL_ROW:
{
urlParser.GetPath((BSTR &)bstrPath);
urlParser.GetClassName((BSTR &)bstrClassName);
}
break;
case -1 :
{
hr = DB_E_NOTFOUND;
break;
}
default:
{
urlParser.GetPath((BSTR &)bstrPath);
break;
}
}
if(SUCCEEDED(hr))
{
try
{
pRow = new CRow(pUnkOuter,m_pCreator);
}
catch(...)
{
SAFE_DELETE_PTR(pRow);
}
if(SUCCEEDED(hr))
{
hr = pRow->InitRow(bstrPath,bstrClassName,GetQualifierFlags(),ROWOPEN);
}
if(SUCCEEDED(hr))
{
DBPROPSET* prgPropertySets;
DBPROPIDSET rgPropIDSet[1];
ULONG cPropSets = 1;
rgPropIDSet[0].cPropertyIDs = 0;
rgPropIDSet[0].guidPropertySet = DBPROPSET_ROWSET;
//==============================================================================
// Get the properties set thru of the current row and set it on the rowset
//==============================================================================
if(SUCCEEDED(hr = m_pUtilProp->GetProperties(PROPSET_ROWSET,0,rgPropIDSet, &cPropSets,&prgPropertySets)))
{
hr = pRow->SetRowProperties(cPropSets,prgPropertySets);
}
//==========================================================================
// Free memory we allocated to by GetProperties
//==========================================================================
m_pUtilProp->m_PropMemMgr.FreeDBPROPSET( cPropSets, prgPropertySets);
if(FAILED(hr = pRow->QueryInterface(riid,(void **)ppOut)))
{
SAFE_DELETE_PTR(pRow);
*ppOut = NULL;
}
}
}
return hr;
}
////////////////////////////////////////////////////////////////////////////////////////
// Function to open a rowset which contains instance of container/scope
////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRow::OpenRowset(LPCOLESTR pwszURL,
IUnknown * pUnkOuter,
REFIID riid,
BOOL bContainer,
IUnknown** ppOut,
ULONG cPropertySets,
DBPROPSET __RPC_FAR rgPropertySets[])
{
HRESULT hr = S_OK;
WCHAR * pstrPath = NULL;
ULONG cPropSets = 1;
CRowset * pRowset = NULL;
DBPROPIDSET rgPropIDSet[1];
VARIANT varValue;
VariantInit(&varValue);
WCHAR * pstrTemp = NULL;
WCHAR * pStrRelPath = NULL;
LPWSTR pStrObjectToOpen = NULL;
rgPropIDSet[0].cPropertyIDs = 0;
rgPropIDSet[0].guidPropertySet = DBPROPSET_ROWSET;
pRowset = new CRowset(pUnkOuter,m_pCreator,m_pCon);
if(!pRowset)
{
hr = E_OUTOFMEMORY;
}
if(SUCCEEDED(hr))
{
INSTANCELISTTYPE ObjInstListType = GetObjectTypeProp(cPropertySets, rgPropertySets);
WCHAR * pStrPath = NULL;
CURLParser urlParser;
CBSTR bstrTemp;
if(!bContainer)
{
// Get the relative path of the current object
if(SUCCEEDED(hr = m_pMap->GetRelativePath(m_pInstance,pStrRelPath)))
{
//===========================================
// If URL is passed open rowset on the URL
//===========================================
if(pwszURL == NULL)
{
pstrTemp = pStrRelPath;
}
//===========================================
// else get URL of the current row
//===========================================
else
{
pstrTemp = new WCHAR[wcslen(pStrRelPath) + wcslen(pwszURL) + wcslen(PATHSEPARATOR) + 1];
if(pstrTemp)
{
wcscpy(pstrTemp,pStrRelPath);
wcscat(pstrTemp,PATHSEPARATOR);
wcscat(pstrTemp,pwszURL);
SAFE_DELETE_ARRAY(pStrRelPath);
pStrRelPath = pstrTemp;
}
else
{
hr = E_OUTOFMEMORY;
}
}
}
}
else
{
CBSTR strObjPath;
VARIANT varDataSource;
VariantInit(&varDataSource);
if(m_pCon)
{
if(SUCCEEDED(hr = m_pCon->GetNodeName(varDataSource.bstrVal)))
{
varDataSource.vt = VT_BSTR;
}
}
else
{
if(SUCCEEDED(hr = m_pCreator->GetDataSrcProperty(DBPROP_INIT_DATASOURCE,varDataSource)) &&
varDataSource.vt == VT_BSTR && varDataSource.bstrVal != NULL )
{
hr = S_OK;
}
else
{
hr = E_UNEXPECTED;
}
}
if(SUCCEEDED(hr))
{
m_pMap->GetInstanceKey(m_pInstance,strObjPath);
if(strObjPath != NULL && _wcsicmp(strObjPath,varDataSource.bstrVal) != 0)
{
hr = m_pMap->GetRelativePath(m_pInstance,pStrObjectToOpen);
}
else
{
pStrObjectToOpen = NULL;
}
}
VariantClear(&varDataSource);
pstrTemp = (WCHAR *)pwszURL;
}
/* bstrTemp.SetStr(pstrTemp);
urlParser.SetURL((BSTR)bstrTemp);
bstrTemp.Clear();
urlParser.GetPath((BSTR &)bstrTemp);
*/
if(SUCCEEDED(hr))
{
// pStrPath = new WCHAR[SysStringLen(bstrTemp) + 1];
// if(pStrPath)
{
// memset(pStrPath , 0 , (SysStringLen(bstrTemp) + 1) * sizeof(WCHAR));
// memcpy(pStrPath,bstrTemp,SysStringLen(bstrTemp) * sizeof(WCHAR));
//==========================================================================
// Call this function to open the object pointed by the URL as scope or
// container
//==========================================================================
hr = pRowset->InitRowset(cPropertySets,rgPropertySets,pstrTemp,pStrObjectToOpen,ObjInstListType);
SAFE_DELETE_ARRAY(pStrPath);
}
/* else
{
hr = E_OUTOFMEMORY;
}
*/ }
}
if(SUCCEEDED(hr))
{
if(FAILED(hr = pRowset->QueryInterface(riid,(void **)ppOut)))
{
SAFE_DELETE_PTR(pRowset);
*ppOut = NULL;
}
}
else
{
SAFE_DELETE_PTR(pRowset);
*ppOut = NULL;
}
SAFE_DELETE_ARRAY(pStrObjectToOpen);
SAFE_DELETE_ARRAY(pStrRelPath);
return hr;
}
////////////////////////////////////////////////////////////////////////////////////////
// Function to set properties of the row
////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRow::SetRowProperties(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();
}
return hr;
}
////////////////////////////////////////////////////////////////////////////////////////
// Function to delete/unlink objects from scope/container
// Object will be deleted if the current object is opened as scope
// object will be unlinked from the current object is opened as container
////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRow::Delete(LPCOLESTR lpszURL,DWORD dwDeleteFlags,DBSTATUS &dbStatus)
{
HRESULT hr = S_OK;
BOOL bContainer = FALSE;
CURLParser urlParser;
CBSTR strTemp;
dbStatus = DBSTATUS_S_OK;
strTemp.SetStr((LPWSTR)lpszURL);
urlParser.SetURL(strTemp);
strTemp.Unbind();
strTemp.Clear();
urlParser.GetPath((BSTR &)strTemp);
bContainer = IsContainer();
if(bContainer)
{
CBSTR strContainer;
strContainer.SetStr(m_strKey);
//==============================================================
// call this function to unlink object pointed by strTemp
// from object pointed by m_strPath acting as container
//==============================================================
if(FAILED(hr = m_pMap->UnlinkObjectFromContainer(strContainer,strTemp)))
{
dbStatus = DBSTATUS_E_UNAVAILABLE;
}
}
else
{
//==============================================================
// Get the instance pointed by the path and then
// delete the object
//==============================================================
CWbemClassWrapper *pInstToDelete = NULL;
pInstToDelete = m_pMap->GetInstance(strTemp);
if(pInstToDelete)
{
hr = m_pMap->DeleteInstance(pInstToDelete);
}
else
{
dbStatus = DBSTATUS_E_UNAVAILABLE;
}
} // else
return hr;
}
////////////////////////////////////////////////////////////////////////////////////////
// Function to move object from one container to another
////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRow::MoveObjects(WCHAR * pStrDstURL,WCHAR * pstrSrcURL, WCHAR *& pNewURL,DBSTATUS &dbStatus)
{
HRESULT hr = S_OK;
BOOL bContainer = FALSE;
CBSTR strSrcObj,strDstObj;
dbStatus = DBSTATUS_S_OK;
//============================================================
// Get the Path string for source and destination objects
//============================================================
strSrcObj.SetStr(pstrSrcURL);
if(GetPathFromURL((BSTR &)strSrcObj))
{
strDstObj.SetStr(pStrDstURL);
if(GetPathFromURL((BSTR &)strDstObj))
{
hr = E_FAIL;
dbStatus = DBSTATUS_E_INVALIDURL;
}
}
else
{
hr = E_FAIL;
dbStatus = DBSTATUS_E_INVALIDURL;
}
if(SUCCEEDED(hr))
{
CBSTR strContainer;
strContainer.SetStr(m_strKey);
//==============================================================
// call this function to unlink object pointed by strSrcObj
// from object pointed by m_strPath acting as container
//==============================================================
if(FAILED(hr = m_pMap->UnlinkObjectFromContainer(strContainer,strSrcObj)))
{
dbStatus = DBSTATUS_E_UNAVAILABLE;
}
else
//==============================================================
// call this function to link object pointed by strSrcObj
// to object pointed by strDstObj acting as container
//==============================================================
if(FAILED(hr = m_pMap->LinkObjectFromContainer(strDstObj,strSrcObj)))
{
dbStatus = DBSTATUS_E_UNAVAILABLE;
}
try
{
pNewURL = new WCHAR[wcslen(pstrSrcURL) +1];
}
catch(...)
{
SAFE_DELETE_ARRAY(pNewURL);
throw;
}
if(pNewURL)
{
//==============================================================
// URL of the object does not change as this is just a move of
// object from one container to another
//==============================================================
wcscpy(pNewURL,pstrSrcURL);
}
else
{
hr = E_OUTOFMEMORY;
}
} // If succeeded(hr)
return hr;
}
////////////////////////////////////////////////////////////////////////////////////////
// Function to get Path from URL string
////////////////////////////////////////////////////////////////////////////////////////
BOOL CRow::GetPathFromURL(BSTR &str)
{
BOOL bRet = FALSE;
CURLParser urlParser;
if(SUCCEEDED( urlParser.SetURL(str)))
{
SysFreeString(str);
urlParser.GetPath(str);
bRet = TRUE;
}
return bRet;
}
////////////////////////////////////////////////////////////////////////////////////////
// Function to check if the current object is to be considered as Scope/Container
////////////////////////////////////////////////////////////////////////////////////////
BOOL CRow::IsContainer()
{
VARIANT vValue;
BOOL bRet = FALSE;
VariantInit(&vValue);
if(SUCCEEDED(GetRowsetProperty(DBPROP_WMIOLEDB_OBJECTTYPE,vValue)))
{
bRet = (V_I4(&vValue) == DBPROPVAL_CONTAINEROBJ) ? TRUE : FALSE;
}
return bRet;
}
////////////////////////////////////////////////////////////////////////////////////////
// Function to move object from one container to another
////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRow::CopyObjects(WCHAR * pStrDstURL,WCHAR * pstrSrcURL, WCHAR *& pNewURL,DBSTATUS &dbStatus)
{
HRESULT hr = S_OK;
BOOL bContainer = FALSE;
CBSTR strSrcObj,strDstObj;
dbStatus = DBSTATUS_S_OK;
//============================================================
// Get the Path string for source and destination objects
//============================================================
strSrcObj.SetStr(pstrSrcURL);
if(GetPathFromURL((BSTR &)strSrcObj))
{
strDstObj.SetStr(pStrDstURL);
if(GetPathFromURL((BSTR &)strDstObj))
{
hr = E_FAIL;
dbStatus = DBSTATUS_E_INVALIDURL;
}
}
else
{
hr = E_FAIL;
dbStatus = DBSTATUS_E_INVALIDURL;
}
if(SUCCEEDED(hr))
{
WCHAR * pstrNewPath = NULL;
if(IsContainer())
{
//==============================================================
// call this function to link object pointed by strSrcObj
// to object pointed by strDstObj acting as container
//==============================================================
hr = m_pMap->LinkObjectFromContainer(strDstObj,strSrcObj);
pstrNewPath = pstrSrcURL;
}
else
{
// Memory for pstrNewPath will be allocated in this function
hr = m_pMap->CloneAndAddNewObjectInScope(strSrcObj,strDstObj,pstrNewPath);
}
if(FAILED(hr))
{
dbStatus = DBSTATUS_E_UNAVAILABLE;
}
try
{
pNewURL = new WCHAR[wcslen(pstrSrcURL) +1];
}
catch(...)
{
SAFE_DELETE_ARRAY(pNewURL);
if(!IsContainer())
{
SAFE_DELETE_ARRAY(pstrNewPath);
}
throw;
}
if(pNewURL)
{
//==============================================================
// URL of the object does not change as this is just a move of
// object from one container to another
//==============================================================
wcscpy(pNewURL,pstrSrcURL);
}
else
{
hr = E_OUTOFMEMORY;
}
if(!IsContainer())
{
SAFE_DELETE_ARRAY(pstrNewPath);
}
} // If succeeded(hr)
return hr;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Function to fetch IUnknown properties
// NTRaid:135384
////////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRow::GetIUnknownColumnValue(DBORDINAL iCol,REFIID riid,IUnknown ** ppUnk,LPCWSTR pStrColName)
{
ROWBUFF * pRowBuff = NULL;
COLUMNDATA * pColumnData = NULL;
void * pSrc = NULL;
BSTR strProp = NULL;
DBTYPE dwDataType = 0;
BYTE * pTemp = NULL;
DBLENGTH uDatLength = 0;
DWORD dwFlags = 0;
HRESULT hr = S_OK;
BOOL bGetData = TRUE;
*ppUnk = NULL;
if(m_pSourcesRowset)
{
// if the column is part of the parent rowset then get data from the parent rowset's buffer
if(iCol == m_pSourcesRowset->GetOrdinalFromColName((WCHAR *)pStrColName))
{
// Set this flag that data to be retrieved is identified
bGetData = FALSE;
//=========================================================
// if data is not yet received then fetch the data
//=========================================================
if(S_OK != m_pSourcesRowset->IsSlotSet(m_hRow))
{
hr = m_pSourcesRowset->GetData(m_hRow);
}
if( (m_pSourcesRowset->m_ulProps & OTHERUPDATEDELETE) &&(m_pSourcesRowset->m_ulLastFetchedRow != m_hRow))
{
if(SUCCEEDED(hr = m_pSourcesRowset->GetDataToLocalBuffer(m_hRow)))
{
m_pSourcesRowset->m_ulLastFetchedRow = m_hRow;
}
}
pRowBuff = m_pSourcesRowset->GetRowBuff(m_hRow , TRUE);
pColumnData = (COLUMNDATA *) ((BYTE *) pRowBuff + m_pSourcesRowset->m_Columns.GetDataOffset(iCol));
pSrc = (pColumnData->pbData);
if(pSrc != NULL)
{
hr = (*(IUnknown **)pSrc)->QueryInterface(riid,(void **)ppUnk);
}
}
}
if(bGetData)
{
strProp = Wmioledb_SysAllocString(pStrColName);
hr = m_pMap->GetProperty(m_pInstance,strProp, pTemp,dwDataType ,uDatLength, dwFlags );
if(SUCCEEDED(hr) && dwDataType == DBTYPE_IUNKNOWN && pTemp != NULL)
{
hr = (*(IUnknown **)pTemp)->QueryInterface(riid,(void **)ppUnk);
}
SAFE_FREE_SYSSTRING(strProp);
}
return hr;
}