|
|
///////////////////////////////////////////////////////////////////////////////////////////
//
// Microsoft WMIOLE DB Provider
// (C) Copyright 1999 Microsoft Corporation. All Rights Reserved.
//
// IRowsetChange interface implementation
//
///////////////////////////////////////////////////////////////////////////////////////////
#include "headers.h"
///////////////////////////////////////////////////////////////////////////////////////////
//
// Sets new data values into fields of a row.
//
// HRESULT
// S_OK The method succeeded
// E_OUTOFMEMORY Out of memory
// DB_E_BADACCESSORHANDLE Bad accessor handle
// DB_E_READONLYACCESSOR Tried to write through a read-only accessor
// DB_E_BADROWHANDLE Invalid row handle
// E_INVALIDARG pData was NULL
// E_FAIL Provider-specific error
// OTHER Other HRESULTs returned by called functions
//
///////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CImpIRowsetChange::SetData ( HROW hRow, // IN Handle of the row in which to set the data
HACCESSOR hAccessor, // IN Handle to the accessor to use
void* pData // IN Pointer to the data
) { BYTE* pbProvRow; HRESULT hr = S_OK; PACCESSOR paccessor = NULL; DWORD dwErrorCount = 0 , dwStatus = DBROWSTATUS_S_OK; VARIANT varProp; BOOL bNewRow = FALSE; CSetStructuredExceptionHandler seh;
TRY_BLOCK;
VariantInit(&varProp);
// Seriliaze the object
CAutoBlock cab(ROWSET->GetCriticalSection());
// Clear Error information
g_pCError->ClearErrorInfo();
hr = m_pObj->GetRowsetProperty(DBPROP_UPDATABILITY,varProp); if(m_pObj->IsZoombie()) { hr = E_UNEXPECTED; } else // If updation is allowed then
if( !(hr == 0 && (DBPROPVAL_UP_CHANGE & varProp.lVal))) { hr = DB_E_NOTSUPPORTED; } else //===========================================================================
// validate the arguments and get the accessor and row pointers
//===========================================================================
if( SUCCEEDED(hr = ValidateArguments(hRow,hAccessor,pData,(PROWBUFF *)&pbProvRow,&paccessor))) { //===========================================================================
// If the number of bindings is zero then there is nothing to update
//===========================================================================
if( paccessor->cBindings == 0) { hr = S_OK; } else { //============================================================================
// Is row handle deleted?
//============================================================================
dwStatus = m_pObj->GetRowStatus(hRow); if(dwStatus == DBROWSTATUS_E_NEWLYINSERTED) { bNewRow = TRUE; } else if( dwStatus != DBROWSTATUS_S_OK) { if(dwStatus == DBROWSTATUS_E_DELETED) { hr = DB_E_DELETEDROW; } else { hr = E_FAIL; } } if(SUCCEEDED(hr)) { // Get data from accessor an put it into the row buffer
hr = ApplyAccessorToData(paccessor->cBindings,paccessor->rgBindings,pbProvRow,pData,dwErrorCount);
if( hr == NOCOLSCHANGED && dwErrorCount > 0) { hr = DB_E_ERRORSOCCURRED; LogMessage("IRowsetChange::SetData:No columns has been modified"); } else // If there is no change in any of the columns then
// there is no need to update
if( !FAILED(hr)) { //==================================================
// update the data on the instance
//==================================================
if(SUCCEEDED(hr = m_pObj->UpdateRowData(hRow,paccessor,bNewRow))) { m_pObj->SetRowStatus(hRow,DBROWSTATUS_S_OK); } } } } }
hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_IRowsetChange);
CATCH_BLOCK_HRESULT(hr,L"IRowsetChange::SetData"); return hr; }
/////////////////////////////////////////////////////////////////////////////////////////////
// Deletes rows from the provider. If Errors on individual rows occur, the DBERRORINFO
// array is updated to reflect the error and S_FALSE is returned instead of S_OK.
//
// HRESULT indicating the status of the method
// S_OK All row handles deleted
// DB_S_ERRORSOCCURRED Some, but not all, row handles deleted
// E_INVALIDARG Arguments did not match spec.
// E_OUTOFMEMORY Could not allocated error array
//
///////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CImpIRowsetChange::DeleteRows (HCHAPTER hChapter, // IN The Chapter handle.
DBCOUNTITEM cRows, // IN Number of rows to delete
const HROW rghRows[], // IN Array of handles to delete
DBROWSTATUS rgRowStatus[] // OUT Error information
) { ULONG ihRow = 0L; ULONG cErrors = 0L; ULONG cRowReleased = 0L; BYTE* pbProvRow = NULL; HRESULT hr = S_OK; DBROWSTATUS * pRowStatus = NULL; VARIANT varProp; CSetStructuredExceptionHandler seh;
TRY_BLOCK;
VariantInit(&varProp);
// Seriliaze the object
CAutoBlock cab(ROWSET->GetCriticalSection());
// Clear Error information
g_pCError->ClearErrorInfo();
hr = m_pObj->GetRowsetProperty(DBPROP_UPDATABILITY,varProp); if(m_pObj->IsZoombie()) { hr = E_UNEXPECTED; } else // If updation is allowed then
if( !(hr == 0 && (DBPROPVAL_UP_DELETE & varProp.lVal))) { hr = DB_E_NOTSUPPORTED; } else
//=====================================================
// If No Row handle, just return.
//=====================================================
if ( cRows > 0 ) {
//=================================================
// Check for Invalid Arguments
//=================================================
if ( (cRows >= 1) && (NULL == rghRows) ){ hr = E_INVALIDARG; } else { //=================================================
// Process row handles
//=================================================
while (ihRow < cRows){
pRowStatus = NULL;
if ( rgRowStatus ) { rgRowStatus[ihRow] = DBROWSTATUS_S_OK; pRowStatus = &rgRowStatus[ihRow]; }
//=============================================
// Is row handle valid
//=============================================
if(FALSE == m_pObj->IsRowExists(rghRows[ihRow])){ // Log Error
if ( rgRowStatus ){ rgRowStatus[ihRow]= DBROWSTATUS_E_INVALID; } cErrors++; ihRow++; continue; }
//=======================================================
// Delete the Row
//=======================================================
if( S_OK != (hr = m_pObj->DeleteRow(rghRows[ihRow],pRowStatus))) cErrors++;
ihRow++;
} //while
} //=================================================
// If everything went OK except errors in rows use
// DB_S_ERRORSOCCURRED.
//=================================================
hr = cErrors ? ( cErrors < cRows ) ? DB_S_ERRORSOCCURRED : DB_E_ERRORSOCCURRED : S_OK ; }
hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_IRowsetChange);
CATCH_BLOCK_HRESULT(hr,L"IRowsetChange::DeleteRows"); return hr; }
/////////////////////////////////////////////////////////////////////////////////////////////
//
// Insert row into provider
//
// Returns: S_OK if data changed successfully
// E_FAIL if Catch all (NULL pData, etc.)
// E_INVALIDARG if pcErrors!=NULL and paErrors==NULL
// E_OUTOFMEMORY if output error array couldn't be allocated
// DB_E_BADACCESSORHANDLE if invalid accessor
//
/////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CImpIRowsetChange::InsertRow (HCHAPTER hChapter, // IN The Chapter handle.
HACCESSOR hAccessor, void* pData, HROW* phRow ) { HRESULT hr = S_OK; CSetStructuredExceptionHandler seh;
TRY_BLOCK;
//====================================================
// Initialize values
//====================================================
if ( phRow ){ *phRow = NULL; } hr = E_FAIL;
DBORDINAL ibind = 0; BYTE* pbProvRow = NULL; HROW irow = 0; DBCOUNTITEM cBindings = 0; DBBINDING* pBinding = NULL; DBCOUNTITEM dwErrorCount = 0; PACCESSOR paccessor = NULL; BOOL fCanHoldRows = FALSE; BSTR strKey = Wmioledb_SysAllocString(NULL); HROW hRowNew = 0; DBORDINAL lQualifColIndex = -1; BOOL bCleanUp = FALSE; VARIANT varProp; CVARIANT cvarData; CDataMap dataMap; VARIANT* pvarData;
CWbemClassWrapper *pNewInst = NULL;
pvarData = &cvarData;
VariantInit(&varProp);
// Seriliaze the object
CAutoBlock cab(ROWSET->GetCriticalSection());
// Clear Error information
g_pCError->ClearErrorInfo();
hr = m_pObj->GetRowsetProperty(DBPROP_UPDATABILITY,varProp); if(m_pObj->IsZoombie()) { hr = E_UNEXPECTED; } else // If updation is allowed then
if( !(hr == 0 && (DBPROPVAL_UP_INSERT & varProp.lVal))) { hr = DB_E_NOTSUPPORTED; } else //====================================================
// Check the Accessor Handle
//====================================================
if ( m_pObj->m_pIAccessor->GetAccessorPtr() == NULL || FAILED( m_pObj->m_pIAccessor->GetAccessorPtr()->GetItemOfExtBuffer( hAccessor, &paccessor)) || paccessor == NULL ) { hr = DB_E_BADACCESSORHANDLE; } else { assert( paccessor );
//====================================================
// Check to see if it is a row accessor
//====================================================
if ( !(paccessor->dwAccessorFlags & DBACCESSOR_ROWDATA) ) hr = DB_E_BADACCESSORTYPE;
// Ensure a source of data.
if ( pData == NULL && paccessor->cBindings ) { hr = E_INVALIDARG ; } else { if (m_pObj->m_ulProps & CANHOLDROWS) { fCanHoldRows = TRUE; }
// Are there any unreleased rows?
if( ((m_pObj->m_pIAccessor->GetBitArrayPtr())->ArrayEmpty() != S_OK) && (!fCanHoldRows) ) { hr = DB_E_ROWSNOTRELEASED; } else // Create the data members to manage the data only the first time
if(!m_pObj->m_bHelperFunctionCreated) { if( SUCCEEDED(hr = m_pObj->CreateHelperFunctions())) { m_pObj->m_bHelperFunctionCreated = TRUE; } }
if(SUCCEEDED(hr)) { // Get new slots for the new row
if (FAILED( hr = GetNextSlots( m_pObj->m_pIBuffer, 1, (HSLOT *)&irow ))) { ; } else // Bind the slot for the row
if (FAILED( m_pObj->Rebind((BYTE *) m_pObj->GetRowBuffFromSlot( (HSLOT)irow, TRUE )))) { ReleaseSlots( m_pObj->m_pIBuffer, irow,1 ); } else { if(IsNullAccessor(paccessor,(BYTE *)pData)) { if(SUCCEEDED(hr = InsertNewRow(irow,hChapter,pNewInst))) { m_pObj->SetRowStatus(irow,DBROWSTATUS_E_NEWLYINSERTED); if(phRow) { *phRow = irow; } } else { bCleanUp = TRUE; } } else { // Get the rowbuffer and set the new bookmark
pbProvRow = (BYTE *) (m_pObj->GetRowBuffFromSlot((HSLOT)irow, TRUE ));
cBindings = paccessor->cBindings; pBinding = paccessor->rgBindings;
// NULL Accessor (set Status to NULL)
// Apply accessor to data.
for (ibind = 0, dwErrorCount = 0; ibind < cBindings; ibind++) {
// If the column is value then get the type of the col is given by the
// qualifier type column
if(( m_pObj->m_uRsType == PROPERTYQUALIFIER || m_pObj->m_uRsType == CLASSQUALIFIER) && pBinding[ibind].iOrdinal == QUALIFIERVALCOL && ibind < cBindings-1) { lQualifColIndex = ibind; continue; }
hr = UpdateDataToRowBuffer(ibind,pbProvRow,pBinding,(BYTE *)pData); if( hr == E_FAIL) { dwErrorCount++; continue; } }
// if the recordset is of qualifer type then update the qualifier value
if( m_pObj->m_uRsType == PROPERTYQUALIFIER || m_pObj->m_uRsType == CLASSQUALIFIER) { if((DB_LORDINAL)lQualifColIndex == -1) { dwErrorCount = cBindings; // to escape the next if condition to throw error
hr = E_FAIL; // the value of the qualifer is not provided for adding
// a new qualifer
} else { //update the qualifier value
ibind = lQualifColIndex; hr = UpdateDataToRowBuffer(ibind,pbProvRow,pBinding,(BYTE *)pData); if( hr == E_FAIL) { dwErrorCount = cBindings; // to escape the next if condition to throw error
} }
} // If all bindings are bad and not a NULL Accessor
if ( ( !cBindings ) || ( dwErrorCount < cBindings ) ) { if(SUCCEEDED(hr = InsertNewRow(irow,hChapter,pNewInst))) { m_pObj->SetRowStatus(irow,DBROWSTATUS_E_NEWLYINSERTED);
//=======================================================
// Update the row data ie. put the property values
// and save the instance
//=======================================================
hr = m_pObj->UpdateRowData(irow,paccessor, TRUE);
if (SUCCEEDED(hr)) { if(phRow) { *phRow = irow; } m_pObj->SetRowStatus(irow,DBSTATUS_S_OK); //=======================================================
// If the rowset is bookmark enabled
//=======================================================
if(m_pObj->m_ulProps & BOOKMARKPROP) { //=======================================================
// Add the bookmark to the bookmark hash table
//=======================================================
m_pObj->m_lLastFetchPos++; ((PROWBUFF)pbProvRow)->dwBmk = m_pObj->m_lLastFetchPos; ((PROWBUFF)pbProvRow)->cbBmk = BOOKMARKSIZE; m_pObj->m_pHashTblBkmark->InsertFindBmk(FALSE,irow,BOOKMARKSIZE,(BYTE *)&((PROWBUFF)pbProvRow)->dwBmk,&irow); } } else { bCleanUp = TRUE; } } // if succeeded(hr) after inserting row and initializing chapters
else { bCleanUp = TRUE; }
} } } // else if(FAILED(REbind())
} // succeeded(hr) after CreateHelperFunctions
} } if(!(FAILED(hr))) { //======================================================================
// If everything went OK except errors in rows use DB_S_ERRORSOCCURRED.
//======================================================================
hr = dwErrorCount ? ( dwErrorCount < cBindings ) ? DB_S_ERRORSOCCURRED : DB_E_ERRORSOCCURRED : S_OK ; }
//==============================================================
// If any failure release the memory allocated for the row
//==============================================================
if( FAILED (hr) && bCleanUp) { //======================================================================
// release the memory allocated for the different columns
//======================================================================
m_pObj->m_pRowData->ReleaseRowData(); ReleaseSlots( m_pObj->m_pIBuffer, irow,1 ); //======================================================================
// release the rows from the instance manager and chapter manager
//======================================================================
m_pObj->ReleaseInstancePointer(irow); } SysFreeString(strKey);
hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_IRowsetChange);
CATCH_BLOCK_HRESULT(hr,L"IRowsetChange::InsertRow"); return hr; }
///////////////////////////////////////////////////////////////////////////////////////////
HRESULT CImpIRowsetChange::ApplyAccessorToData( DBCOUNTITEM cBindings, DBBINDING* pBinding,BYTE* pbProvRow, void* pData,DWORD & dwErrorCount )
{ PCOLUMNDATA pColumnData; DBORDINAL icol, ibind; DBTYPE dwSrcType; DBTYPE dwDstType; DBLENGTH dwSrcLength; DBLENGTH* pdwDstLength; DBLENGTH dwDstMaxLength; DBSTATUS dwSrcStatus; DBSTATUS* pdwDstStatus; DBSTATUS* pdwSrcStatus; DWORD dwPart; BYTE b; void* pDst; void* pSrc; void* pTemp; CDataMap dataMap; CVARIANT cvarData; VARIANT *pvarData = &cvarData; CDataMap map; ULONG cColChanged = 0; BOOL bUseDataConvert = TRUE; LONG_PTR lCIMType = 0;
HRESULT hr = NOCOLSCHANGED;
for (ibind = 0, dwErrorCount = 0; ibind < cBindings; ibind++) { bUseDataConvert = TRUE; icol = pBinding[ibind].iOrdinal; pColumnData = (COLUMNDATA *) (pbProvRow + m_pObj->m_Columns.GetDataOffset(icol));
dwSrcType = pBinding[ibind].wType; dwDstType = (DBTYPE)pColumnData->dwType; // m_pObj->m_Columns.ColumnType(icol);
if(dwDstType == DBTYPE_EMPTY || dwDstType == DBTYPE_NULL) { dwDstType = m_pObj->m_Columns.ColumnType(icol); } dwSrcType = pBinding[ibind].wType; pdwDstLength = &(pColumnData->dwLength); pdwDstStatus = &(pColumnData->dwStatus); dwDstMaxLength = pBinding[ibind].cbMaxLen;
dwPart = pBinding[ibind].dwPart;
if ((dwPart & DBPART_VALUE) == 0){
if (((dwPart & DBPART_STATUS) && (*(ULONG *) ((BYTE*) pData + pBinding[ibind].obStatus) & DBSTATUS_S_ISNULL)) || ((dwPart & DBPART_LENGTH) && *(ULONG *) ((BYTE*) pData + pBinding[ibind].obLength) == 0)) {
pSrc = &b; b = 0x00; } else{ hr = E_FAIL ; break; } } else{ pSrc = (void *) ((BYTE*) pData + pBinding[ibind].obValue); }
dwSrcLength = (dwPart & DBPART_LENGTH) ? *(ULONG *) ((BYTE*) pData + pBinding[ibind].obLength) : 0; dwSrcStatus = (dwPart & DBPART_STATUS) ? *(ULONG *) ((BYTE*) pData + pBinding[ibind].obStatus) : DBSTATUS_S_OK; pdwSrcStatus = (dwPart & DBPART_STATUS) ? (ULONG *) ((BYTE*) pData + pBinding[ibind].obStatus) : NULL;
//==========================================================================
// if the columnd is of type readonly then don't do anything
//==========================================================================
if((m_pObj->m_Columns.ColumnFlags(icol) & DBCOLUMNFLAGS_WRITE) == 0) { if(pdwSrcStatus != NULL) *pdwSrcStatus = DBSTATUS_E_READONLY; dwErrorCount++; continue; }
hr = g_pIDataConvert->GetConversionSize(dwSrcType, dwDstType, &dwSrcLength, pdwDstLength, pSrc);
try { pDst = new BYTE[*pdwDstLength]; } 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; }
if( dwSrcType != VT_NULL && dwSrcType != VT_EMPTY && bUseDataConvert == TRUE && pSrc != NULL) { hr = g_pIDataConvert->DataConvert( dwSrcType, dwDstType, dwSrcLength, pdwDstLength, pSrc, pDst, dwDstMaxLength, dwSrcStatus, pdwDstStatus, pBinding[ibind].bPrecision, // bPrecision for conversion to DBNUMERIC
pBinding[ibind].bScale, // bScale for conversion to DBNUMERIC
DBDATACONVERT_SETDATABEHAVIOR);
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 = map.ConvertAndCopyArray((SAFEARRAY *)pSrc,(SAFEARRAY **)pDst, dwSrcType,dwDstType,pdwDstStatus); if( *pdwDstStatus == DBSTATUS_E_CANTCONVERTVALUE) { *pdwDstLength = 0; dwErrorCount++; }
} else { pDst = NULL; *pdwDstLength = 0; *pdwDstStatus = DBSTATUS_S_ISNULL; }
if( SUCCEEDED(hr)) { if(pDst != NULL && dwDstType == VT_BSTR) { pTemp = *(BSTR **)pDst; } else { pTemp = pDst; } }
// If data is modified then
if(hr == S_OK && (map.CompareData(dwDstType,pColumnData->pbData,pTemp) == FALSE) && !( pColumnData->pbData == NULL && *pdwDstLength == 0)) { // Release the previous data
pColumnData->ReleaseColumnData();
// If no data is there in the column ie. data i null then
if(*pdwDstLength > 0) { // this variable gets value only if the CIMTYPE is array
lCIMType = -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) { lCIMType = m_pObj->m_Columns.GetCIMType(icol); }
if(dwDstType == VT_BSTR) { pTemp = *(BSTR **)pDst; } else { pTemp = pDst; }
// Convert the new data to Variant , THis function returns the status if not
// able to conver the data
hr = dataMap.MapAndConvertOLEDBTypeToCIMType(dwDstType,pTemp,*pdwDstLength,*pvarData,lCIMType); }
if( SUCCEEDED(hr)) { // Set the data
if( S_OK == (hr = pColumnData->SetData(cvarData,dwDstType))) { cColChanged++; }
// Set the data to modified
pColumnData->dwStatus |= COLUMNSTAT_MODIFIED;
cvarData.Clear();
} else { // Set the data to modified
*pdwDstStatus |= hr;
}
} SAFE_DELETE_ARRAY(pDst);
if (FAILED(hr)){ dwErrorCount++; // rounding or truncation or can't coerce
} hr = S_OK; } // If the number of errors is equal or greater than
// the number of bindings and the error is only
// due to the readonly attribute of every column then
// set the error
if(cColChanged == 0) { hr = NOCOLSCHANGED; } else { hr = dwErrorCount ? DB_S_ERRORSOCCURRED : S_OK ; }
return hr; }
/////////////////////////////////////////////////////////////////////////////////////////////
// Function to validate the arguments
/////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CImpIRowsetChange::ValidateArguments( HROW hRow, HACCESSOR hAccessor, const void *pData, PROWBUFF *pprowbuff, PACCESSOR *ppkgaccessor) { HRESULT hr = S_OK; // NTRaid:111831 - 111832
// 06/07/00
PROWBUFF pRowBuff = NULL ; PACCESSOR pAccessor = NULL;
//========================================================
// Check if the row exists
//========================================================
if(FALSE == m_pObj->IsRowExists(hRow)) { hr = DB_E_BADROWHANDLE; } else { //============================================================================
// Row is fetched but data is not yet fetched??
//============================================================================
if ( m_pObj->IsSlotSet(hRow) != S_OK ) { hr = m_pObj->GetData(hRow); if(FAILED(hr)) { hr = DB_E_BADROWHANDLE ; } } if (SUCCEEDED(hr) && m_pObj->m_pIAccessor->GetAccessorPtr() == NULL || FAILED( m_pObj->m_pIAccessor->GetAccessorPtr()->GetItemOfExtBuffer( hAccessor, &pAccessor)) || pAccessor == NULL ){
//========================================================================
// Check the Accessor Handle
//========================================================================
return DB_E_BADACCESSORHANDLE ; }
if(SUCCEEDED(hr)) { assert( pAccessor );
//============================================================================
// Check to see if it is a row accessor
//============================================================================
if ( !((pAccessor)->dwAccessorFlags & DBACCESSOR_ROWDATA) ) { hr = DB_E_BADACCESSORTYPE; } else if ( pData == NULL){
//============================================================================
// Ensure a source of data.
//============================================================================
hr = E_INVALIDARG; } else {
pRowBuff = m_pObj->GetRowBuff((ULONG) hRow, TRUE ); } }
}
if(pprowbuff != NULL) { *pprowbuff = pRowBuff; }
if(ppkgaccessor != NULL) { *ppkgaccessor = pAccessor; }
return hr; }
/////////////////////////////////////////////////////////////////////////////////////////////
// Function with compares dat of a particular type and checks whether both are same or not
/////////////////////////////////////////////////////////////////////////////////////////////
BOOL CImpIRowsetChange::CompareData(DBTYPE dwType,void * pData1 , void *pData2) {
BOOL bRet = FALSE; long lType = VT_NULL;
if(pData1 == NULL || pData2 == NULL) { if(pData1 == pData2) { bRet = TRUE; } } if(bRet == FALSE) { // If the type is of some array
if (dwType & VT_ARRAY) { lType = VT_ARRAY; } else { lType = dwType; }
switch( lType ){
case VT_NULL: case VT_EMPTY: bRet = TRUE; break;
case CIM_FLAG_ARRAY: bRet = FALSE; break;
case CIM_SINT8: case CIM_UINT8: if(!memcmp(pData1,pData2,1)) bRet = TRUE; break;
case CIM_CHAR16: case CIM_SINT16: case CIM_UINT16: case CIM_BOOLEAN: if(!memcmp(pData1,pData2,2)) bRet = TRUE; break;
case CIM_SINT32: case CIM_UINT32: case CIM_REAL32: if(!memcmp(pData1,pData2,4)) bRet = TRUE; break;
case CIM_SINT64: case CIM_UINT64: case CIM_REAL64: case CIM_DATETIME: if(!memcmp(pData1,pData2,8)) bRet = TRUE; break;
case CIM_STRING:
if( pData1 != NULL && pData2 != NULL) { if(!_wcsicmp((WCHAR *)pData1,(WCHAR *)pData2)) bRet = TRUE; }
break;
case CIM_REFERENCE: break;
case CIM_OBJECT: break;
case VT_VARIANT: break;
default: assert( !"Unmatched OLEDB Data Type to CIMTYPE." ); } } return bRet; }
HRESULT CImpIRowsetChange::UpdateDataToRowBuffer(DBCOUNTITEM ibind,BYTE * pbProvRow,DBBINDING* pBinding,BYTE *pData) {
//====================================================
// Initialize values
//====================================================
HRESULT hr = S_OK; DBORDINAL icol = 0; DBTYPE dwSrcType = 0; DBTYPE dwDstType = 0; void* pSrc = NULL; void* pDst = NULL; void* pTemp = NULL; DBLENGTH dwSrcLength = 0; DBLENGTH* pdwDstLength = 0; DBLENGTH dwDstMaxLength = 0; DWORD dwSrcStatus = 0; DWORD* pdwDstStatus = 0; DWORD dwPart = 0; PCOLUMNDATA pColumnData = NULL; BYTE b = 0; VARIANT* pvarData = NULL; BSTR strPropName = Wmioledb_SysAllocString(NULL); BOOL bUseDataConvert = TRUE; DWORD dwCIMType = 0; CVARIANT cvarData; CDataMap dataMap;
pvarData = &cvarData; icol = pBinding[ibind].iOrdinal; pColumnData = (COLUMNDATA *) (pbProvRow + m_pObj->m_Columns.GetDataOffset(icol));
dwSrcType = pBinding[ibind].wType; pDst = &(pColumnData->pbData); pdwDstLength = &(pColumnData->dwLength); pdwDstStatus = &(pColumnData->dwStatus); dwDstMaxLength = pBinding[ibind].cbMaxLen;
dwPart = pBinding[ibind].dwPart;
// If the column is value then get the type of the col is given by the
// qualifier type column
if(( m_pObj->m_uRsType == PROPERTYQUALIFIER || m_pObj->m_uRsType == CLASSQUALIFIER) && pBinding[ibind].iOrdinal == QUALIFIERVALCOL ) { dwDstType = *(DBTYPE *)((COLUMNDATA *) (pbProvRow + m_pObj->m_Columns.GetDataOffset(QUALIFIERTYPECOL)))->pbData; pColumnData->dwType = VT_VARIANT; } else { dwDstType = m_pObj->m_Columns.ColumnType(icol); pColumnData->dwType = dwDstType; }
if ((dwPart & DBPART_VALUE) == 0) { if (((dwPart & DBPART_STATUS) && (*(ULONG *) ((BYTE*) pData + pBinding[ibind].obStatus) & DBSTATUS_S_ISNULL)) || ((dwPart & DBPART_LENGTH) && *(ULONG *) ((BYTE*) pData + pBinding[ibind].obLength) == 0)) { pSrc = &b; b = 0x00; } else { if ( dwPart & DBPART_STATUS ) { *(DBSTATUS *) ((BYTE*) pData + pBinding[ibind].obStatus) = DBSTATUS_E_UNAVAILABLE; } hr = E_FAIL; } } else { pSrc = (void *) ((BYTE*) pData + pBinding[ibind].obValue); }
if(SUCCEEDED(hr)) { dwSrcLength = (dwPart & DBPART_LENGTH) ? *(ULONG *) ((BYTE*) pData + pBinding[ibind].obLength) : 0;
dwSrcStatus = (dwPart & DBPART_STATUS) ? *(ULONG *) ((BYTE*) pData + pBinding[ibind].obStatus) : DBSTATUS_S_OK;
if(!( dwSrcType == DBTYPE_HCHAPTER || dwDstType == DBTYPE_HCHAPTER)) { strPropName = Wmioledb_SysAllocString(m_pObj->m_Columns.ColumnName(icol)); //==========================================================================
// if the columnd is a system property then set it to readonly
//==========================================================================
if(TRUE == m_pObj->m_pMap->IsSystemProperty(strPropName)) { SysFreeString(strPropName); pColumnData->dwStatus = DBSTATUS_E_READONLY; hr = E_FAIL; } else { SysFreeString(strPropName);
// Get the conversion size for the column
if(SUCCEEDED(hr = g_pIDataConvert->GetConversionSize(dwSrcType, dwDstType, &dwSrcLength, pdwDstLength, pSrc))) { hr = E_OUTOFMEMORY; try { pDst = new BYTE[*pdwDstLength]; } catch(...) { SAFE_DELETE_ARRAY(pDst); throw; } if(pDst) { hr = S_OK; // 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) { // Convert the data to the type which can be update to WBEM
hr = g_pIDataConvert->DataConvert( dwSrcType, dwDstType, dwSrcLength, pdwDstLength, pSrc, pDst, dwDstMaxLength, dwSrcStatus, pdwDstStatus, pBinding[ibind].bPrecision, // bPrecision for conversion to DBNUMERIC
pBinding[ibind].bScale, // bScale for conversion to DBNUMERIC
DBDATACONVERT_SETDATABEHAVIOR);
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 || FAILED(hr)) { *pdwDstLength = 0; hr = E_FAIL; } } else { pDst = NULL; *pdwDstLength = 0; *pdwDstStatus = DBSTATUS_S_ISNULL; }
if (SUCCEEDED(hr)) { if(pDst != NULL && pColumnData->dwType == VT_BSTR) { pTemp = *(BSTR **)pDst; } else { pTemp = pDst; }
// If no data is there in the column ie. data i null then
if(*pdwDstLength > 0) {
// 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_pObj->m_Columns.GetCIMType(icol); }
if(pColumnData->dwType == VT_BSTR) { pTemp = *(BSTR **)pDst; } else { pTemp = pDst; } // Convert the new data to Variant, this function return DBSTATUS if
// not able to convert
hr = dataMap.MapAndConvertOLEDBTypeToCIMType(dwDstType,pTemp,*pdwDstLength,*pvarData,dwCIMType); }
if(SUCCEEDED(hr)) { // Set the data
hr = pColumnData->SetData(cvarData,pColumnData->dwType); } else { pColumnData->dwStatus |= hr; }
if (SUCCEEDED(hr)) { // Set the data to modified
pColumnData->dwStatus |= COLUMNSTAT_MODIFIED; }
cvarData.Clear(); } } // if (pDst)
} // IF succeeded(getting conversion size)
} // if valid property name
} // if the column in not a chapter
}
SAFE_DELETE_ARRAY(pDst);
return hr; }
BOOL CImpIRowsetChange::IsNullAccessor(PACCESSOR phAccessor,BYTE * pData ) { BOOL bNullAccessor = TRUE; DWORD dwPart = 0; DWORD dwStatatus = 0;
if(phAccessor->cBindings) { for(DBORDINAL cBinding = 0 ; cBinding < phAccessor->cBindings ; cBinding++) { dwPart = phAccessor->rgBindings[cBinding].dwPart; dwStatatus = (dwPart & DBPART_STATUS) ? *(ULONG *) ((BYTE*) pData + phAccessor->rgBindings[cBinding].obStatus) : DBSTATUS_S_OK; if(dwStatatus != DBSTATUS_S_IGNORE) { bNullAccessor = FALSE; break; } } } return bNullAccessor; }
HRESULT CImpIRowsetChange::InsertNewRow(HROW hRow, HCHAPTER hChapter,CWbemClassWrapper *& pNewInst) { HRESULT hr = S_OK; BSTR strKey = NULL;
//==========================
// Carry out the insert.
// Set the RowHandle
//==========================
if(SUCCEEDED(hr = m_pObj->InsertNewRow(&pNewInst))) { //===========================================================================
// if there is atleast one row retrieved and there are neseted columns
// then allocate rows for the child recordsets
//===========================================================================
if(m_pObj->m_cNestedCols > 0 )
{ if(m_pObj->m_ppChildRowsets == NULL) m_pObj->AllocateAndInitializeChildRowsets();
//=====================================================================
// Fill the HCHAPTERS for the column
//=====================================================================
hr = m_pObj->FillHChaptersForRow(pNewInst,strKey); }
if(SUCCEEDED(hr)) { //===================================================
// if the class is not representing qualilfiers
//===================================================
if(m_pObj->m_bIsChildRs == FALSE) { //=================================================
// add instance pointer to instance manager
//=================================================
hr = m_pObj->m_InstMgr->AddInstanceToList(hRow,pNewInst,strKey,hRow); } //=================================================================================
// if rowset is refering to qualifiers then add the row to the particular chapter
//=================================================================================
else { // add instance pointer to instance manager
hr = m_pObj->m_pChapterMgr->AddHRowForChapter(hChapter,hRow, NULL ,hRow); } } }
return hr; }
|