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