527 lines
15 KiB
C++
527 lines
15 KiB
C++
|
///////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Microsoft WMIOLE DB Provider
|
||
|
// (C) Copyright 1999 Microsoft Corporation. All Rights Reserved.
|
||
|
//
|
||
|
// CQualifierRowFetchObj object implementation
|
||
|
//
|
||
|
//
|
||
|
///////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
#include "headers.h"
|
||
|
#include "WmiOleDBMap.h"
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////////////
|
||
|
// Function which fetches required number of rows
|
||
|
///////////////////////////////////////////////////////////////////////////////////////
|
||
|
HRESULT CQualifierRowFetchObj::FetchRows(CRowset * pRowset,
|
||
|
HCHAPTER hChapter, // IN The Chapter handle.
|
||
|
DBROWOFFSET lRowOffset, // IN Rows to skip before reading
|
||
|
DBROWCOUNT cRows, // IN Number of rows to fetch
|
||
|
DBCOUNTITEM* pcRowsObtained, // OUT Number of rows obtained
|
||
|
HROW ** prghRows) // OUT Array of Hrows obtained)
|
||
|
|
||
|
{
|
||
|
DBCOUNTITEM cRowsTmp = 0;
|
||
|
HROW irow, ih;
|
||
|
PROWBUFF prowbuff = NULL;
|
||
|
HRESULT hr = S_OK;
|
||
|
HROW * prghRowsTemp = NULL;
|
||
|
HROW hRowCurrent = 0;
|
||
|
HSLOT hSlot = -1;
|
||
|
BOOL bAlreadyDataRetrieved = FALSE;
|
||
|
BOOL bAlreadyFetched = FALSE;
|
||
|
CVARIANT varKey;
|
||
|
BOOL bFetchBack = FALSE;
|
||
|
HROW hRowTemp;
|
||
|
BSTR strQualifier;
|
||
|
CBSTR strKey;
|
||
|
LONG_PTR lFetchPos = 0;
|
||
|
BOOL bHRowsAllocated = FALSE;
|
||
|
DBROWCOUNT ulMax = 0;
|
||
|
BOOL bMaxRowsExceed = FALSE;
|
||
|
|
||
|
CWbemClassWrapper *pInst = NULL;
|
||
|
|
||
|
if(cRows != 0)
|
||
|
{
|
||
|
{
|
||
|
VARIANT varTemp;
|
||
|
VariantInit(&varTemp);
|
||
|
pRowset->GetRowsetProperty(DBPROP_MAXOPENROWS,varTemp);
|
||
|
|
||
|
ulMax = varTemp.lVal;
|
||
|
VariantClear(&varTemp);
|
||
|
}
|
||
|
|
||
|
|
||
|
//=======================================================
|
||
|
// If already maximum rows are opened then return
|
||
|
//=======================================================
|
||
|
if( pRowset->m_ulRowRefCount >= (DBROWCOUNT)ulMax)
|
||
|
{
|
||
|
hr = DB_S_ROWLIMITEXCEEDED;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
|
||
|
if(pRowset->m_bIsChildRs == FALSE)
|
||
|
{
|
||
|
assert(pRowset->m_pInstance != NULL);
|
||
|
}
|
||
|
|
||
|
//========================
|
||
|
// Fetch Data
|
||
|
//========================
|
||
|
if (lRowOffset)
|
||
|
{
|
||
|
if(hChapter > 0)
|
||
|
{
|
||
|
pInst = pRowset->m_pChapterMgr->GetInstance(hChapter);
|
||
|
}
|
||
|
else
|
||
|
if(pRowset->m_bIsChildRs == FALSE)
|
||
|
{
|
||
|
pInst = pRowset->m_pInstance;
|
||
|
}
|
||
|
//===================================
|
||
|
// Calculate the new position
|
||
|
//===================================
|
||
|
hr = pRowset->ResetRowsetToNewPosition(lRowOffset,pInst);
|
||
|
if( hr != S_OK )
|
||
|
{
|
||
|
pRowset->SetStatus(hChapter , STAT_ENDOFCURSOR);
|
||
|
hr = DB_S_ENDOFROWSET ;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(hr == S_OK)
|
||
|
{
|
||
|
|
||
|
if(0 >( lFetchPos = GetFirstFetchPos(pRowset,cRows,lRowOffset)))
|
||
|
{
|
||
|
hr = DB_E_BADSTARTPOSITION;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
cRowsTmp = cRows >= 0 ? cRows : cRows * (-1);
|
||
|
ulMax = ulMax - pRowset->m_ulRowRefCount;
|
||
|
if(ulMax < (DBROWCOUNT)cRowsTmp)
|
||
|
{
|
||
|
bMaxRowsExceed = TRUE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ulMax = cRowsTmp;
|
||
|
}
|
||
|
cRowsTmp = 0;
|
||
|
|
||
|
pRowset->m_FetchDir = (LONG_PTR)cRows < 0 ? FETCHDIRBACKWARD : FETCHDIRFORWARD;
|
||
|
bFetchBack = (LONG_PTR)cRows < 0 ? TRUE : FALSE;
|
||
|
// cRows = cRows >=0 ? cRows : cRows * (-1);
|
||
|
//=======================================================================
|
||
|
// If any rows is to be retrieved then allocate memory for the HROWS
|
||
|
//=======================================================================
|
||
|
if (ulMax )
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
prghRowsTemp = (HROW *) g_pIMalloc->Alloc( ulMax * sizeof( HROW ));
|
||
|
}
|
||
|
catch(...)
|
||
|
{
|
||
|
if(prghRowsTemp != NULL)
|
||
|
{
|
||
|
g_pIMalloc->Free(prghRowsTemp);
|
||
|
}
|
||
|
throw;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(prghRowsTemp == NULL)
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
}
|
||
|
}
|
||
|
if(SUCCEEDED(hr))
|
||
|
{
|
||
|
memset(prghRowsTemp,0,ulMax * sizeof( HROW ));
|
||
|
|
||
|
hRowTemp = pRowset->m_hRowLastFetched;
|
||
|
for (irow =1; irow <= (DBCOUNTITEM)ulMax; irow++)
|
||
|
{
|
||
|
bAlreadyFetched = FALSE;
|
||
|
bAlreadyDataRetrieved = FALSE;
|
||
|
|
||
|
if(pRowset->m_bIsChildRs == TRUE)
|
||
|
{
|
||
|
//==============================================================================
|
||
|
// Find out whether qualifier is already obtained
|
||
|
//==============================================================================
|
||
|
pInst = pRowset->m_pChapterMgr->GetInstance(hChapter);
|
||
|
pRowset->m_pChapterMgr->GetInstanceKey(hChapter,(BSTR *)&strKey);
|
||
|
}
|
||
|
else
|
||
|
if( pRowset->m_pInstance != NULL)
|
||
|
{
|
||
|
pInst = pRowset->m_pInstance;
|
||
|
}
|
||
|
|
||
|
switch(pRowset->m_uRsType)
|
||
|
{
|
||
|
case CLASSQUALIFIER:
|
||
|
hr = pRowset->GetNextClassQualifier(pInst,strQualifier,bFetchBack);
|
||
|
break;
|
||
|
|
||
|
case PROPERTYQUALIFIER:
|
||
|
hr = pRowset->GetNextPropertyQualifier(pInst,pRowset->m_strPropertyName,strQualifier,bFetchBack);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if(S_OK != hr)
|
||
|
{
|
||
|
pRowset->SetStatus(hChapter , STAT_ENDOFCURSOR);
|
||
|
hr = DB_S_ENDOFROWSET;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if( hr == S_OK)
|
||
|
{
|
||
|
strKey.Clear();
|
||
|
strKey.Unbind();
|
||
|
strKey.SetStr(strQualifier);
|
||
|
if(pRowset->m_bIsChildRs == TRUE)
|
||
|
{
|
||
|
hRowTemp = pRowset->m_pChapterMgr->GetHRow(hChapter,strQualifier);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hRowTemp = pRowset->m_InstMgr->GetHRow(strQualifier);
|
||
|
}
|
||
|
|
||
|
|
||
|
if( (LONG)hRowTemp > 0)
|
||
|
{
|
||
|
bAlreadyFetched = TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if( bAlreadyFetched == TRUE)
|
||
|
{
|
||
|
hRowCurrent = hRowTemp;
|
||
|
|
||
|
if(pRowset->m_bIsChildRs == TRUE)
|
||
|
{
|
||
|
hSlot = pRowset->m_pChapterMgr->GetSlot(hRowCurrent);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hSlot = pRowset->m_InstMgr->GetSlot(hRowCurrent);
|
||
|
}
|
||
|
if( hSlot != -1)
|
||
|
{
|
||
|
bAlreadyDataRetrieved = TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//====================================================
|
||
|
// Get the HROW if row is not already fetched
|
||
|
//====================================================
|
||
|
if( bAlreadyFetched == FALSE)
|
||
|
hRowCurrent = pRowset->GetNextHRow();
|
||
|
|
||
|
//=====================================================
|
||
|
// Get the data if data is already not fetched
|
||
|
//=====================================================
|
||
|
if(bAlreadyDataRetrieved == FALSE)
|
||
|
{
|
||
|
|
||
|
hSlot = -1;
|
||
|
if (SUCCEEDED( hr = GetNextSlots( pRowset->m_pIBuffer, 1, &hSlot )))
|
||
|
{
|
||
|
if (FAILED( pRowset->Rebind((BYTE *) pRowset->GetRowBuffFromSlot( hSlot, TRUE ))))
|
||
|
{
|
||
|
hr = E_FAIL;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
hRowCurrent = hSlot;
|
||
|
|
||
|
//=================================================================================================
|
||
|
// if the other updates visible property is set to false ,then get the data to the local buffer
|
||
|
//=================================================================================================
|
||
|
if(!( pRowset->m_ulProps & OTHERUPDATEDELETE))
|
||
|
{
|
||
|
|
||
|
if(FAILED(hr = pRowset->GetInstanceDataToLocalBuffer(pInst,hSlot,strQualifier)))
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//===========================================================================
|
||
|
// if there is atleast one row retrieved and there are neseted columns
|
||
|
// then allocate rows for the child recordsets
|
||
|
//===========================================================================
|
||
|
if(pRowset->m_cNestedCols > 0 )
|
||
|
|
||
|
{
|
||
|
if(pRowset->m_ppChildRowsets == NULL)
|
||
|
{
|
||
|
pRowset->AllocateAndInitializeChildRowsets();
|
||
|
}
|
||
|
|
||
|
//=====================================================================
|
||
|
// Fill the HCHAPTERS for the column
|
||
|
//=====================================================================
|
||
|
if(S_OK != (hr = pRowset->FillHChaptersForRow(pInst,strKey)))
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
if(SUCCEEDED(hr))
|
||
|
{
|
||
|
//===================================================
|
||
|
// if the rowset is not a child rowset
|
||
|
//===================================================
|
||
|
if(pRowset->m_bIsChildRs == FALSE)
|
||
|
{
|
||
|
//=================================================
|
||
|
// add instance pointer to instance manager
|
||
|
//=================================================
|
||
|
if(FAILED(hr = pRowset->m_InstMgr->AddInstanceToList(hRowCurrent,pInst,strQualifier,hSlot)))
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
//=================================================================================
|
||
|
// if rowset is refering to qualifiers then add the row to the particular chapter
|
||
|
//=================================================================================
|
||
|
else
|
||
|
{
|
||
|
// add instance pointer to instance manager
|
||
|
if(FAILED(hr = pRowset->m_pChapterMgr->AddHRowForChapter(hChapter,hRowCurrent, NULL ,hSlot)))
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
pRowset->m_pChapterMgr->SetInstance(hChapter,pInst, strQualifier ,hRowCurrent);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
} //if(bAlreadyDataRetrieved == FALSE)
|
||
|
// prghRowsTemp[irow-1] = hRowCurrent;
|
||
|
prghRowsTemp[irow-1] = hSlot;
|
||
|
|
||
|
SysFreeString(strQualifier);
|
||
|
strKey.Clear();
|
||
|
strKey.Unbind();
|
||
|
strQualifier = Wmioledb_SysAllocString(NULL);
|
||
|
}
|
||
|
|
||
|
if(SUCCEEDED(hr))
|
||
|
{
|
||
|
cRowsTmp = irow - 1; //Irow will be +1 because of For Loop
|
||
|
|
||
|
//=====================================================================
|
||
|
// Through fetching many rows of data
|
||
|
//
|
||
|
// Allocate row handles for client. Note that we need to use IMalloc
|
||
|
// for this. Should only malloc cRowsTmp, instead of ulMax.
|
||
|
// Should malloc ulMax, since client will assume it's that big.
|
||
|
//=====================================================================
|
||
|
|
||
|
if ( *prghRows == NULL && cRowsTmp )
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
*prghRows = (HROW *) g_pIMalloc->Alloc( cRowsTmp * sizeof( HROW ));
|
||
|
}
|
||
|
catch(...)
|
||
|
{
|
||
|
if(*prghRows)
|
||
|
{
|
||
|
g_pIMalloc->Free(prghRows);
|
||
|
}
|
||
|
throw;
|
||
|
}
|
||
|
bHRowsAllocated = TRUE;
|
||
|
memset(*prghRows,0,cRowsTmp * sizeof( HROW ));
|
||
|
}
|
||
|
|
||
|
if ( *prghRows == NULL && cRowsTmp )
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY ;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//=====================================================================
|
||
|
// Fill in the status information: Length, IsNull. May be able to wait
|
||
|
// until first call to GetData, but have to do it sometime.
|
||
|
//
|
||
|
// Suggest keeping an array of structs of accessor info. One element is
|
||
|
// whether accessor requires any status info or length info.
|
||
|
//
|
||
|
// Then we could skip this whole section.
|
||
|
//
|
||
|
// Added check for cRowsTmp to MarkRows call. Don't want to call if
|
||
|
// cRowsTmp==0.
|
||
|
// (Range passed to MarkRows is inclusive, so can't specify marking 0 rows.)
|
||
|
//
|
||
|
// Note that SetSlots is a CBitArray member function -- not an IBuffer function.
|
||
|
//
|
||
|
// Added row-wise reference counts and cursor-wise reference counts.
|
||
|
//
|
||
|
// Set row handles, fix data length field and compute data status field.
|
||
|
//=======================================================================
|
||
|
pRowset->m_cRows = cRowsTmp;
|
||
|
|
||
|
// set the first position if it is zero
|
||
|
if(lFetchPos == 0)
|
||
|
{
|
||
|
lFetchPos = 1;
|
||
|
}
|
||
|
|
||
|
for (ih =0; ih < (ULONG) pRowset->m_cRows; ih++)
|
||
|
{
|
||
|
|
||
|
|
||
|
//=============================================================================
|
||
|
// Increment the rows-read count,
|
||
|
// then store it as the bookmark in the very first DWORD of the row.
|
||
|
//=============================================================================
|
||
|
prowbuff = pRowset->GetRowBuff( prghRowsTemp[ih], TRUE );
|
||
|
|
||
|
//=======================================================================================
|
||
|
// Insert the bookmark and its row number (from 1...n) into a hash table.
|
||
|
// This allows us to quickly determine the presence of a row in mem, given the bookmark.
|
||
|
// The bookmark is contained in the row buffer, at the very beginning.
|
||
|
// Bookmark is the row number within the entire result set [1...num_rows_read].
|
||
|
|
||
|
// This was a new Bookmark, not in memory,
|
||
|
// so return to user (in *prghRows) the hRow we stored.
|
||
|
//=======================================================================================
|
||
|
prowbuff->ulRefCount++;
|
||
|
pRowset->m_ulRowRefCount++;
|
||
|
|
||
|
(*prghRows)[ih] = prghRowsTemp[ih]; // (HROW) ( irow );
|
||
|
pRowset->m_hRowLastFetched = prghRowsTemp[ih];
|
||
|
|
||
|
// if bookmark property is true then initialize the bookmark
|
||
|
if(pRowset->m_ulProps & BOOKMARKPROP)
|
||
|
{
|
||
|
if(ih != 0)
|
||
|
{
|
||
|
lFetchPos = (pRowset->m_FetchDir == FETCHDIRFORWARD ) ? lFetchPos + 1 : lFetchPos -1;
|
||
|
}
|
||
|
|
||
|
prowbuff->dwBmk = lFetchPos;
|
||
|
prowbuff->cbBmk = BOOKMARKSIZE;
|
||
|
pRowset->m_lLastFetchPos = lFetchPos;
|
||
|
|
||
|
// Add bookmark to the hashtable
|
||
|
pRowset->m_pHashTblBkmark->InsertFindBmk(FALSE,prghRowsTemp[ih],prowbuff->cbBmk,(BYTE *)&(prowbuff->dwBmk),(HROW *)&hSlot);
|
||
|
}
|
||
|
|
||
|
} // for loop
|
||
|
|
||
|
} // else for memory allocation for HROWS
|
||
|
|
||
|
} // if(succeeded(hr))
|
||
|
|
||
|
if(SUCCEEDED(hr))
|
||
|
{
|
||
|
*pcRowsObtained = cRowsTmp;
|
||
|
}
|
||
|
|
||
|
//===================================================
|
||
|
// set return value if MAX_ROWS is exceeded
|
||
|
//===================================================
|
||
|
if( hr == S_OK && bMaxRowsExceed == TRUE)
|
||
|
{
|
||
|
hr = DB_S_ROWLIMITEXCEEDED;
|
||
|
}
|
||
|
|
||
|
} // else for some basic parameter checking
|
||
|
} // if(Succeeded(hr)) after setting the resetting offset
|
||
|
} // else after checking for MAX rows limit
|
||
|
} // if(cRows != 0)
|
||
|
|
||
|
|
||
|
//==============================================
|
||
|
// free the temporary memory allocated
|
||
|
//==============================================
|
||
|
|
||
|
if(FAILED(hr))
|
||
|
{
|
||
|
// for(irow = irowFirst ; irow <= hRowTemp ; irow++)
|
||
|
for (ih =0; ih < (ULONG) cRowsTmp; ih++)
|
||
|
{
|
||
|
if(prghRowsTemp[ih] != 0)
|
||
|
{
|
||
|
if(pRowset->m_bIsChildRs == FALSE)
|
||
|
{
|
||
|
pRowset->m_InstMgr->DeleteInstanceFromList(prghRowsTemp[ih]);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pRowset->m_pChapterMgr->DeleteHRow(prghRowsTemp[ih]);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if(pcRowsObtained)
|
||
|
{
|
||
|
*pcRowsObtained = 0;
|
||
|
}
|
||
|
|
||
|
// if HROWS for output parameter is allcated by this method
|
||
|
// then release them
|
||
|
if(prghRows && bHRowsAllocated == TRUE)
|
||
|
{
|
||
|
g_pIMalloc->Free(prghRows);
|
||
|
prghRows = NULL;
|
||
|
}
|
||
|
else
|
||
|
if(prghRows)
|
||
|
{
|
||
|
*prghRows = NULL;
|
||
|
}
|
||
|
if(pcRowsObtained)
|
||
|
{
|
||
|
*pcRowsObtained = 0;
|
||
|
}
|
||
|
if(strQualifier != NULL)
|
||
|
{
|
||
|
SysFreeString(strQualifier);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//==============================================
|
||
|
// free the temporary memory allocated
|
||
|
//==============================================
|
||
|
if(prghRowsTemp)
|
||
|
{
|
||
|
g_pIMalloc->Free(prghRowsTemp);
|
||
|
prghRowsTemp = NULL;
|
||
|
}
|
||
|
|
||
|
// reset the starting position to the original position
|
||
|
if(lRowOffset && (FAILED(hr) || (hr != S_OK && cRowsTmp == 0)))
|
||
|
{
|
||
|
pRowset->ResetRowsetToNewPosition(lRowOffset * (-1),pInst);
|
||
|
}
|
||
|
|
||
|
|
||
|
return hr;
|
||
|
|
||
|
}
|