|
|
///////////////////////////////////////////////////////////////////////////////////
//
// Microsoft WMIOLE DB Provider
// (C) Copyright 1999 Microsoft Corporation. All Rights Reserved.
//
// CRowFetchObj class implementation
//
//
///////////////////////////////////////////////////////////////////////////////////
#include "headers.h"
#include "WmiOleDBMap.h"
/////////////////////////////////////////////////////////////////////////////////////
////CRowFetchObj class Implementation
/////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// Function which fetches data and puts it into the given buffer
// NTRaid:111834
// 06/07/00
///////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRowFetchObj::FetchData(CRowset * pRowset, HROW hRow, //IN Row Handle
HACCESSOR hAccessor, //IN Accessor to use
void *pData ) {
// NTRaid:111834
// 06/13/00
PACCESSOR pAccessor = NULL; DBORDINAL icol = 0; DBORDINAL ibind = 0; ROWBUFF *pRowBuff = NULL; COLUMNDATA *pColumnData = NULL; DBBINDING *pBinding = NULL; DBROWCOUNT cBindings = NULL; ULONG ulErrorCount = 0; DBTYPE dwSrcType = 0; DBTYPE dwDstType = 0; void *pSrc = NULL; void *pDst = NULL; DBLENGTH ulSrcLength = 0; DBLENGTH *pulDstLength = NULL; DBLENGTH ulDstMaxLength = 0; DBSTATUS dwSrcStatus = 0; DBSTATUS *pdwDstStatus = NULL; DWORD dwPart = 0; HRESULT hr = S_OK; HSLOT hSlot = 0; BOOL bUseDataConvert = TRUE;
CWbemClassWrapper * pInst = NULL; CDataMap dataMap;
//========================================================================================
// Coerce data for row 'hRow', according to hAccessor. Put in location 'pData'.
// Offsets and types are in hAccessor's bindings.
//
// Return S_OK if all lossless conversions,
// return DB_S_ERRORSOCCURED if lossy conversion (truncation, rounding, etc.)
// Return E_FAIL, etc., if horrible errors.
// GetItemOfExtBuffer is basically operator[].
// It takes an index (or handle) (referenced from 1...n),
// and a ptr for where to write the data.
//
// It holds ptrs to a variable-length ACCESSOR struct.
// So we get the ACCESSOR ptr for the client's accessor handle.
//========================================================================================
assert( pRowset->m_pIAccessor->GetAccessorPtr()); hr = pRowset->m_pIAccessor->GetAccessorPtr()->GetItemOfExtBuffer( hAccessor, &pAccessor ); if (FAILED( hr ) || pAccessor == NULL) { hr = DB_E_BADACCESSORHANDLE; } else { assert( pAccessor ); cBindings = pAccessor->cBindings; pBinding = pAccessor->rgBindings;
//========================================================================================
// Ensure a place to put data, unless the accessor is the null accessor then
// a NULL pData is okay.
//========================================================================================
if ( pData == NULL && cBindings != 0 ) { hr = E_INVALIDARG ; } else //========================================================================================
// IsSlotSet returns S_OK if row is marked.
// S_FALSE if row is not marked.
// The "mark" means that there is data present in the row.
// Rows are [1...n], slot marks are [0...n-1].
//========================================================================================
if (pRowset->IsSlotSet(hRow ) != S_OK) { hr = DB_E_BADROWHANDLE; } else //===================================================================
// if data is not already fetched to the memory ( which is done
// if other updatedelete is false)
//===================================================================
if( (pRowset->m_ulProps & OTHERUPDATEDELETE) && (pRowset->m_ulLastFetchedRow != hRow)) { if(SUCCEEDED (hr = pRowset->GetDataToLocalBuffer(hRow))) { pRowset->m_ulLastFetchedRow = hRow; }
} if(SUCCEEDED(hr)) { //========================================================================================
// Internal error for a 0 reference count on this row,
// since we depend on the slot-set stuff.
//========================================================================================
pRowBuff = pRowset->GetRowBuff( (ULONG) hRow, TRUE ); assert( pRowBuff->ulRefCount );
//========================================================================================
// Check for the Deleted Row
//========================================================================================
ulErrorCount = 0; for (ibind = 0; ibind < (DBORDINAL)cBindings; ibind++) { bUseDataConvert = TRUE; icol = pBinding[ibind].iOrdinal; // pColumnData = pRowBuff->GetColumnData(icol);
//========================================================================================
// If bookmark is not requested by setting the DBPROP_BOOKMARK property
// then skip getting the bookmark
//========================================================================================
if(!(pRowset->m_ulProps & BOOKMARKPROP) && icol == 0) { continue; } else //========================================================================================
// if it is a bookmark column get the bookmark column from the ROWBUFF Structure
//========================================================================================
if(icol == 0) { dwSrcType = DBTYPE_I4; pSrc = &pRowBuff->dwBmk; ulSrcLength = pRowBuff->cbBmk; dwSrcStatus = DBSTATUS_S_OK; } else { pColumnData = (COLUMNDATA *) ((BYTE *) pRowBuff + pRowset->m_Columns.GetDataOffset(icol));
dwSrcType = (DBTYPE)pColumnData->dwType ; //pRowset->m_Columns.ColumnType(icol);
//===================================================================
// FIXXX More work is to be done on this
//===================================================================
if( dwSrcType == DBTYPE_BSTR ) { pSrc = &(pColumnData->pbData); } else { pSrc = (pColumnData->pbData); }
ulSrcLength = pColumnData->dwLength; dwSrcStatus = pColumnData->dwStatus;
if(dwSrcType == DBTYPE_HCHAPTER) { dwSrcType = DBTYPE_UI4; } }
ulDstMaxLength = pBinding[ibind].cbMaxLen; dwDstType = pBinding[ibind].wType; dwPart = pBinding[ibind].dwPart;
pDst = dwPart & DBPART_VALUE ? ((BYTE*) pData + pBinding[ibind].obValue) : NULL; pulDstLength = dwPart & DBPART_LENGTH ? (DBLENGTH *) ((BYTE*) pData + pBinding[ibind].obLength) : NULL; pdwDstStatus = dwPart & DBPART_STATUS ? (DBSTATUS *) ((BYTE*) pData + pBinding[ibind].obStatus) : NULL;
//==========================================================
// if the column is of type chapter then consider that
// as a of type long as HCHAPTER is a ULONG value
//==========================================================
if(dwDstType == DBTYPE_HCHAPTER) { dwDstType = DBTYPE_UI4; } if((dwSrcType & DBTYPE_ARRAY) && (dwDstType & DBTYPE_ARRAY)) { bUseDataConvert = FALSE; } if( dwSrcType != VT_NULL && dwSrcType != VT_EMPTY && bUseDataConvert == TRUE && pSrc != NULL) { BSTR strData; if( dwDstType == DBTYPE_BSTR && pDst == NULL) { void **pTemp = &pDst; *pTemp = (void *)&strData; }
hr = g_pIDataConvert->DataConvert( dwSrcType, dwDstType, ulSrcLength, pulDstLength, pSrc, pDst, ulDstMaxLength, dwSrcStatus, pdwDstStatus, pBinding[ibind].bPrecision, // bPrecision for conversion to DBNUMERIC
pBinding[ibind].bScale, // bScale for conversion to DBNUMERIC
DBDATACONVERT_DEFAULT);
if(!(dwPart & DBPART_VALUE) && pulDstLength != NULL) { hr =g_pIDataConvert->GetConversionSize(dwSrcType,dwDstType,&ulSrcLength,pulDstLength,pSrc); }
if(!(dwPart & DBPART_VALUE) && dwDstType == DBTYPE_BSTR ) { if(pulDstLength != NULL) { *pulDstLength = SysStringLen(strData); } SysFreeString(strData); }
if(hr == DB_E_UNSUPPORTEDCONVERSION && pdwDstStatus != NULL) { *pdwDstStatus = DBSTATUS_E_CANTCONVERTVALUE; } } else if(bUseDataConvert == FALSE && pSrc != NULL ) {
if(pDst != NULL) { //========================================================================================
// Call this function to get the array in the destination address
//========================================================================================
hr = dataMap.ConvertAndCopyArray((SAFEARRAY *)pSrc,(SAFEARRAY **)pDst, dwSrcType,dwDstType,pdwDstStatus); } if(pulDstLength != NULL) { *pulDstLength = sizeof(SAFEARRAY); }
if( pdwDstStatus != NULL && *pdwDstStatus == DBSTATUS_E_CANTCONVERTVALUE && pulDstLength != NULL) { *pulDstLength = 0; } } else { if(pulDstLength) { *pulDstLength = 0; } if(pdwDstStatus) { *pdwDstStatus = DBSTATUS_S_ISNULL; } } if (hr != S_OK ) { ulErrorCount++; // can't coerce
} } // for loop
} // if succeeded(hr)
} // else for check for bad accessor
//===================================================================
// 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 clear all the allocated buffer if any error occurs while getting data
///////////////////////////////////////////////////////////////////////////////////////////
void CRowFetchObj::ClearRowBuffer(void *pData, DBBINDING *pBinding, int nCurCol) { ULONG *pulDstLength; DWORD *pdwDstStatus; CDataMap map; void *pDst; DWORD dwPart;
//========================================================================================
// Check for the Deleted Row
//========================================================================================
for (int ibind = 0; ibind < nCurCol; ibind++) { dwPart = pBinding[ibind].dwPart;
pDst = dwPart & DBPART_VALUE ? ((BYTE*) pData + pBinding[ibind].obValue) : NULL; pulDstLength = dwPart & DBPART_LENGTH ? (ULONG *) ((BYTE*) pData + pBinding[ibind].obLength) : NULL; pdwDstStatus = dwPart & DBPART_STATUS ? (ULONG *) ((BYTE*) pData + pBinding[ibind].obStatus) : NULL;
if(pDst) { map.ClearData(pBinding[ibind].wType,(BYTE *)pDst); } if(pulDstLength) { *pulDstLength = 0; } if(pdwDstStatus) { *pdwDstStatus = 0; } } }
///////////////////////////////////////////////////////////////////////////////////////////
// Function which get the position of the first row to be fetched
///////////////////////////////////////////////////////////////////////////////////////////
LONG_PTR CRowFetchObj::GetFirstFetchPos(CRowset *pRowset,DBCOUNTITEM cRows,DBROWOFFSET lOffset) { FETCHDIRECTION lFetchDir; LONG_PTR lFirstPos = -1;
lFetchDir = (LONG_PTR)cRows < 0 ? FETCHDIRBACKWARD : FETCHDIRFORWARD;
if( cRows != 0) { lFirstPos = pRowset->m_lLastFetchPos + lOffset;
if((pRowset->m_FetchDir != FETCHDIRNONE) && pRowset->m_FetchDir != lFetchDir) { } else { lFirstPos = (LONG_PTR)cRows < 0 ? lFirstPos - 1 : lFirstPos + 1; } }
if(lFirstPos <= 0) { lFirstPos = -1; }
return lFirstPos; }
///////////////////////////////////////////////////////////////////////////////////////////
// Function which get the position of the first row to be fetched
// NTRaid:111770
// 06/07/00
///////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRowFetchObj::FetchRowsByBookMark(CRowset * pRowset, HCHAPTER hChapter, // IN The Chapter handle.
DBROWCOUNT cRows, // IN Number of rows to fetch
const DBBKMARK rgcbBookmarks[], //@parm IN | an array of bookmark sizes
const BYTE* rgpBookmarks[], //@parm IN | an array of pointers to bookmarks
HROW rghRows[], // OUT Array of Hrows obtained
DBROWSTATUS rgRowStatus[]) // OUT status of rows
{
DBCOUNTITEM ibmk, cErrors, cRowsObtained; PROWBUFF prowbuff; HROW hrow, hrowFound; HRESULT hr; BYTE* pbBmk; DBBKMARK cbBmk; DBROWSTATUS dbrowstatus; ULONG_PTR ulLastFetchPos; FETCHDIRECTION lFetchDir; DBROWOFFSET lOffset = 0; HROW * phRow;
ulLastFetchPos = pRowset->m_lLastFetchPos; lFetchDir = pRowset->m_FetchDir;
if(pRowset->m_FetchDir == FETCHDIRNONE) { pRowset->m_FetchDir = FETCHDIRFORWARD; }
//========================================================================================
// Now, loop thru all supplied bookmarks.
//========================================================================================
for (ibmk =0, cErrors =0; ibmk < (DBCOUNTITEM)cRows; ibmk++) { pbBmk = (BYTE*)&rgpBookmarks[ibmk]; cbBmk = pbBmk? rgcbBookmarks[ibmk] : 0;
//========================================================================================
// Must be a valid bookmark
//========================================================================================
if (cbBmk != BOOKMARKSIZE) { dbrowstatus = DBROWSTATUS_E_INVALID; hrow = DB_NULL_HROW; }
//========================================================================================
// We might already have this bookmark in our hashtable.
//========================================================================================
else if (pRowset->m_pHashTblBkmark->InsertFindBmk(TRUE, 0, cbBmk, pbBmk, &hrow) == S_OK) { //========================================================================================
// Row handle for this Bookmark was already in memory,
// so return the row handle that was found.
//========================================================================================
prowbuff = pRowset->GetRowBuffFromSlot(hrow); if (pRowset->GetRowStatus(hrow) & DBROWSTATUS_E_DELETED) { dbrowstatus = DBROWSTATUS_E_INVALID; hrow = DB_NULL_HROW; } else { dbrowstatus = DBROWSTATUS_S_OK; prowbuff->ulRefCount++; } }
else //==========================================================================================
// if bookmark not alread present then fetch the row and put the bookmark in hash table
//==========================================================================================
{ lOffset = *((ULONG *)pbBmk) - pRowset->m_lLastFetchPos;
lOffset = (pRowset->m_FetchDir == FETCHDIRFORWARD) ? --lOffset : ++lOffset;
cRowsObtained = 0; phRow = &hrow;
//====================================================================================
// Use a utility object method to fetch the row with the bookmark.
//====================================================================================
hr = FetchRows(pRowset,hChapter ,lOffset,ONE_ROW, &cRowsObtained, &phRow);
//==========================================================================================
// In case of any problem with fetching the row make an entry
// in the error array.
//==========================================================================================
if (FAILED(hr) || cRowsObtained < ONE_ROW) { dbrowstatus = (hr == E_OUTOFMEMORY) ? DBROWSTATUS_E_OUTOFMEMORY : DBROWSTATUS_E_INVALID; hrow = DB_NULL_HROW; } else { prowbuff = pRowset->GetRowBuffFromSlot(hrow); //==========================================================================
// Now, enter this bookmark in our hashtable.
//==========================================================================
if (SUCCEEDED(hr)) { prowbuff->cbBmk = BOOKMARKSIZE; prowbuff->dwBmk = rgcbBookmarks[ibmk];
hr = (pRowset->m_pHashTblBkmark)->InsertFindBmk(FALSE, hrow, prowbuff->cbBmk, pbBmk, &hrowFound); if (FAILED(hr)) { ReleaseSlots(pRowset->m_pIBuffer,hrow, ONE_ROW); dbrowstatus = DBROWSTATUS_E_OUTOFMEMORY; hrow = DB_NULL_HROW; } else { assert(hr == S_FALSE); dbrowstatus = DBROWSTATUS_S_OK; } } } }
// mark status.
if (rgRowStatus) rgRowStatus[ibmk] = dbrowstatus;
if (dbrowstatus != DBROWSTATUS_S_OK) cErrors++;
// Put the rowhandle in the output array, and
rghRows[ibmk] = (HROW)hrow; }
// Reverting back the state of the rowset
pRowset->m_lLastFetchPos = ulLastFetchPos; pRowset->m_FetchDir = lFetchDir;
return cErrors ? (cErrors < (ULONG)cRows) ? DB_S_ERRORSOCCURRED : DB_E_ERRORSOCCURRED : S_OK;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Function to fetch the next few rows as requested from the bookmark specified
///////////////////////////////////////////////////////////////////////////////////////////
HRESULT CRowFetchObj::FetchNextRowsByBookMark(CRowset * pRowset, HCHAPTER hChapter, // IN The Chapter handle.
DBBKMARK cbBookmark, // size of BOOKMARK
const BYTE * pBookmark, // The bookmark from which fetch should start
DBROWOFFSET lRowsOffset, DBROWCOUNT cRows, DBCOUNTITEM * pcRowsObtained, HROW ** prghRows) // array containing the row handles
{ HRESULT hr = S_OK;
//=====================================================================
// Must be a valid bookmark
//=====================================================================
if (cbBookmark != BOOKMARKSIZE && cbBookmark != STD_BOOKMARKLENGTH) { hr = DB_E_BADBOOKMARK;
} else //=============================================================================
// If the bookmark is a standard bookmark
//=============================================================================
if( cbBookmark == STD_BOOKMARKLENGTH) { switch(*pBookmark) { case DBBMK_INVALID: return DB_E_BADBOOKMARK;
case DBBMK_FIRST: lRowsOffset = lRowsOffset - pRowset->m_lLastFetchPos ; if(cRows < 0) { hr = DB_S_ENDOFROWSET; } break;
case DBBMK_LAST: lRowsOffset = lRowsOffset + pRowset->m_lRowCount - pRowset->m_lLastFetchPos; if(cRows > 0) { hr = DB_S_ENDOFROWSET; } break;
}
} //=============================================================================
// If not a standard bookmark
//=============================================================================
else { lRowsOffset = lRowsOffset + (*(ULONG_PTR *)pBookmark - pRowset->m_lLastFetchPos);
// Adjust the offset , so that the first received row is correct
lRowsOffset = cRows > 0 ? lRowsOffset -1 : lRowsOffset + 1;
}
if(hr == S_OK) { if( 0 > (LONG)(lRowsOffset + pRowset->m_lLastFetchPos) && (lRowsOffset + pRowset->m_lLastFetchPos) > pRowset->m_lRowCount) { hr = DB_E_BADSTARTPOSITION; } else { // NTRaid : 134987
// 07/12/00
ULONG_PTR lPrevPos = pRowset->m_lLastFetchPos; FETCHDIRECTION lFetchDir = pRowset->GetCurFetchDirection();
// set the direction flag on the enumerator so that the
// enumerator returns instance starting from the last instance
if(cbBookmark == STD_BOOKMARKLENGTH && *pBookmark == DBBMK_LAST) { pRowset->SetCurFetchDirection(FETCHDIRFORWARD); }
//=============================================================================
// call this function to fetch rows
//=============================================================================
if(SUCCEEDED(hr = FetchRows(pRowset,hChapter ,lRowsOffset,cRows, pcRowsObtained, prghRows))) { HRESULT hrLocal = S_OK; // Adjust the position of the enumerator after fetching
ULONG_PTR lOffSetAdjust = lPrevPos -pRowset->m_lLastFetchPos; if(SUCCEEDED(hrLocal = pRowset->ResetRowsetToNewPosition(lOffSetAdjust,pRowset->m_pInstance))) { pRowset->m_lLastFetchPos = lPrevPos; pRowset->SetCurFetchDirection(lFetchDir); }
if(FAILED(hrLocal)) { hr = hrLocal; } } } } return hr;
}
|