windows-nt/Source/XPSP1/NT/admin/wmi/wbem/adapters/oledb/irowset.cpp
2020-09-26 16:20:57 +08:00

1191 lines
38 KiB
C++

///////////////////////////////////////////////////////////////////////////
//
// Microsoft WMIOLE DB Provider
//
// (C) Copyright 1999 Microsoft Corporation. All Rights Reserved.
//
// IROWSET.CPP IRowsetLocate interface implementation
//
///////////////////////////////////////////////////////////////////////////
#include "headers.h"
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// Retrieves data from the rowset's cache
//
// Returns one of the following values:
// S_OK Method Succeeded
// DB_S_ERRORSOCCURED Could not coerce a column value
// DB_E_BADACCESSORHANDLE Invalid Accessor given
// DB_E_BADROWHANDLE Invalid row handle given
// E_INVALIDARG pData was NULL
// OTHER Other HRESULTs returned by called functions
//
/////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CImpIRowsetLocate::GetData( HROW hRow, //IN Row Handle
HACCESSOR hAccessor, //IN Accessor to use
void *pData ) //OUT Pointer to buffer where data should go.
{
HRESULT hr = DB_E_BADROWHANDLE;
CSetStructuredExceptionHandler seh;
TRY_BLOCK;
// Seriliaze the object
CAutoBlock cab(ROWSET->GetCriticalSection());
g_pCError->ClearErrorInfo();
if(m_pObj->IsZoombie())
{
hr = E_UNEXPECTED;
}
else
if( hRow > 0)
{
//============================================================
// Call this function of RowFetch Object to fetch data
//============================================================
hr = m_pObj->m_pRowFetchObj->FetchData(m_pObj,hRow,hAccessor,pData);
}
hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_IRowsetLocate);
CATCH_BLOCK_HRESULT(hr,L"IRowset::GetData");
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// CImpIRowset::GetNextRows
//
// Fetches rows in a sequential style, remembering the previous position
//
// Returns one of the following values:
// S_OK Method Succeeded
// DB_S_ENDOFROWSET Reached end of rowset
// DB_E_CANTFETCHBACKWARDS cRows was negative and we can't fetch backwards
// DB_E_ROWSNOTRELEASED Must release all HROWs before calling GetNextRows
// E_FAIL Provider-specific error
// E_INVALIDARG pcRowsObtained or prghRows was NULL
// E_OUTOFMEMORY Out of Memory
// OTHER Other HRESULTs returned by called functions
///////////////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CImpIRowsetLocate::GetNextRows ( 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
)
{
HRESULT hr;
CSetStructuredExceptionHandler seh;
TRY_BLOCK;
// Seriliaze the object
CAutoBlock cab(ROWSET->GetCriticalSection());
// clear error information
g_pCError->ClearErrorInfo();
//========================================================================
// Check the HChapter is of the current rowset is valid
//========================================================================
if(m_pObj->IsZoombie())
{
hr = E_UNEXPECTED;
}
else
if((m_pObj->m_bIsChildRs == TRUE && hChapter == DB_NULL_HCHAPTER) || (LONG_PTR)hChapter < 0 ||
m_pObj->m_bIsChildRs == FALSE && hChapter != 0)
{
hr = DB_E_BADCHAPTER;
}
else
{
//========================================================================
// Check the rowset parameters to see if we support this request
//========================================================================
if(SUCCEEDED(hr = CheckParameters(pcRowsObtained, lRowOffset, cRows, prghRows)))
{
if(hChapter)
{
hr = m_pObj->CheckAndInitializeChapter(hChapter);
}
if(SUCCEEDED(hr))
{
// 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))
{
//========================================================================
// Are there any unreleased rows?
//========================================================================
if( ((m_pObj->m_pIAccessor->GetBitArrayPtr())->ArrayEmpty() != S_OK) && !(m_pObj->m_ulProps & CANHOLDROWS) )
{
hr = DB_E_ROWSNOTRELEASED;
}
else
{
//============================================================
// Call this function of Rowfetch object to fetch rows
//============================================================
hr = m_pObj->m_pRowFetchObj->FetchRows(m_pObj,hChapter,lRowOffset,cRows,pcRowsObtained,prghRows);
} // else
} // if succeeded(hr)
} // if succeeded(hr)
} // if succeeded(hr)
}
hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_IRowset);
CATCH_BLOCK_HRESULT(hr,L"IRowset::GetNextRows");
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Releases row handles
//
// Returns one of the following values:
// S_OK | success
// DB_S_ERRORSOCCURRED | some elements of rghRows were invalid
// DB_E_ERRORSOCCURRED | all elements of rghRows were invalid
// E_INVALIDARG | rghRows was a NULL pointer and crow > 0
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CImpIRowsetLocate::ReleaseRows ( DBCOUNTITEM cRows, // IN Number of rows to release
const HROW rghRows[], // IN Array of handles of rows to be released
DBROWOPTIONS rgRowOptions[], // IN Additional Options
DBREFCOUNT rgRefCounts[], // OUT array of ref counts of released rows
DBROWSTATUS rgRowStatus[] // OUT status array of for input rows
)
{
HRESULT hr = S_OK;
ULONG ihRow = 0L;
ULONG cErrors = 0L;
ROWBUFF *pRowBuff = NULL;
BOOL bBuffFlag = FALSE;
LONG lRowRefCount = 0;
CSetStructuredExceptionHandler seh;
TRY_BLOCK;
// Seriliaze the object
CAutoBlock cab(ROWSET->GetCriticalSection());
// clear error information
g_pCError->ClearErrorInfo();
if(cRows == 0)
{
hr = S_OK;
}
else
//============================================================================
// check params
//============================================================================
if ( cRows && !rghRows )
{
hr = E_INVALIDARG;
// return g_pCError->PostHResult(E_INVALIDARG,&IID_IRowset);
}
else
{
ihRow = 0;
// If any rows is fetched data slotlist would have been initialized otherwise
// return invallid rows
if(!m_pObj->m_bHelperFunctionCreated)
{
for (ihRow = 0; ihRow < cRows; ihRow++)
{
if(rgRefCounts)
{
rgRefCounts[ihRow] = 0;
}
if(rgRowStatus)
{
rgRowStatus[ihRow] = DBROWSTATUS_E_INVALID;
}
}
hr = DB_E_ERRORSOCCURRED;
// return g_pCError->PostHResult(DB_E_ERRORSOCCURRED,&IID_IRowset);
}
else
{
while ( ihRow < cRows )
{
bBuffFlag = FALSE;
lRowRefCount = 0;
//=============================================================
// if HROW is invalid mark it and continue with the next row
//=============================================================
if(((LONG) rghRows[ihRow]) <= 0)
{
if( rgRowStatus != NULL)
rgRowStatus[ihRow] = DBROWSTATUS_E_INVALID;
ihRow++;
cErrors++;
continue;
}
hr = m_pObj->IsSlotSet(rghRows[ihRow]);
if( hr == S_OK)
{
//=============================================================
// Get the buffer address if it is allocated
//=============================================================
pRowBuff=m_pObj->GetRowBuff((ULONG) rghRows[ihRow], TRUE);
if(pRowBuff != NULL)
{
bBuffFlag = TRUE;
}
}
//=========================================================================
// check the row handle
//=========================================================================
if(m_pObj->m_ulRowRefCount && (TRUE == m_pObj->IsRowExists(rghRows[ihRow])))
{
if(bBuffFlag == TRUE)
{
--pRowBuff->ulRefCount;
lRowRefCount = pRowBuff->ulRefCount;
}
//=====================================================================
// Found valid row, so decrement reference counts.
// (Internal error for refcount to be 0 here, since slot set.)
//=====================================================================
--m_pObj->m_ulRowRefCount;
//=====================================================================
// stuff new refcount into caller's array
//=====================================================================
if ( rgRefCounts )
{
rgRefCounts[ihRow] = lRowRefCount;
}
if ( rgRowStatus )
{
rgRowStatus[ihRow] = DBROWSTATUS_S_OK;
}
if ( lRowRefCount == 0 )
{
if(bBuffFlag == TRUE)
{
// Bind the row data to the rowdata mem manager
if (FAILED( m_pObj->Rebind((BYTE *) pRowBuff)))
{
if( rgRowStatus != NULL)
{
rgRowStatus[ihRow] = DBROWSTATUS_E_FAIL;
}
++cErrors;
//return g_pCError->PostHResult(E_FAIL,&IID_IRowset);
}
else
{
//============================================================
// release the memory allocated for the different columns
//============================================================
m_pObj->m_pRowData->ReleaseRowData();
}
if(m_pObj->m_ulProps & BOOKMARKPROP)
{
m_pObj->m_pHashTblBkmark->DeleteBmk((ULONG)rghRows[ihRow]);
}
if(m_pObj->m_ulLastFetchedRow == rghRows[ihRow])
{
m_pObj->m_ulLastFetchedRow = 0;
}
// release the slots
ReleaseSlots( m_pObj->m_pIBuffer, m_pObj->GetSlotForRow(rghRows[ihRow]), 1 );
}
// release the rows from the instance manager and chapter manager
m_pObj->ReleaseInstancePointer(rghRows[ihRow]);
}
}
else
{
//=====================================================================
// It is an error for client to try to release a row
// for which "IsSetSlot" is false. Client gave us an invalid handle.
// Ignore it (we can't release it...) and report error when done.
//=====================================================================
if ( rgRefCounts )
{
rgRefCounts[ihRow] = 0;
}
if ( rgRowStatus )
{
rgRowStatus[ihRow] = DBROWSTATUS_E_INVALID;
}
++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 );
} // else for if(!m_pObj->m_bHelperFunctionCreated)
} // else for if ( cRows && !rghRows )
hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_IRowset);
CATCH_BLOCK_HRESULT(hr,L"IRowset::ReleaseRows");
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Repositions the next fetch position to the start of the rowset
//
// - all rows must be released before calling this method
// - it is not expensive to Restart us, because we are from a single table
//
//
// Returns one of the following values:
// S_OK | Method Succeeded
// DB_E_ROWSNOTRELEASED | All HROWs must be released before calling
// DB_S_COMMANDREEXECUTED | The command was re-executed. This can happen when a method is
// is executed or RestartPosition is called on Forwardonly rowset
// DB_E_BADCHAPTER | HCHAPTER passed was invalid
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CImpIRowsetLocate::RestartPosition( HCHAPTER hChapter ) // IN The Chapter handle.
{
BOOL fCanHoldRows = FALSE;
BOOL fLiteralIdentity = FALSE;
HRESULT hr = S_OK;
CSetStructuredExceptionHandler seh;
TRY_BLOCK;
// Seriliaze the object
CAutoBlock cab(ROWSET->GetCriticalSection());
// clear error information
g_pCError->ClearErrorInfo();
if(m_pObj->IsZoombie())
{
hr = E_UNEXPECTED;
}
else
if((m_pObj->m_bIsChildRs == TRUE && hChapter == DB_NULL_HCHAPTER) || (LONG_PTR)hChapter < 0 ||
m_pObj->m_bIsChildRs == FALSE && hChapter != 0)
{
hr = DB_E_BADCHAPTER;
//return g_pCError->PostHResult(DB_E_BADCHAPTER,&IID_IRowset);
}
else
{
//=========================================================================
// If no rows are fetched in this rowset after opening don't do anything
// if bitarray is NULL no rows are fetched till now
//=========================================================================
if(!(m_pObj->m_hRow == 0 ||
m_pObj->m_pIAccessor->GetBitArrayPtr() == NULL))
{
/*
//========================================================================
// Get the LiteralIdentity property
//========================================================================
if( ((m_pObj->m_pIAccessor->GetBitArrayPtr())->ArrayEmpty() != S_OK) && !(m_pObj->m_ulProps & LITERALIDENTITY) ){
fLiteralIdentity = TRUE;
}
*/
//========================================================================
// Are there any unreleased rows?
//========================================================================
if( ((m_pObj->m_pIAccessor->GetBitArrayPtr())->ArrayEmpty() != S_OK) && !(m_pObj->m_ulProps & CANHOLDROWS) )
{
hr = DB_E_ROWSNOTRELEASED;
//return g_pCError->PostHResult(DB_E_ROWSNOTRELEASED,&IID_IRowset);
}
else
{
/* //============================================================================
// If LiteralIdentity is on reset SlotList
//============================================================================
if ( fLiteralIdentity )
ResetSlotList( m_pObj->m_pIBuffer );
*/
//============================================================================
// set "next fetch" position to the start of the rowset
//============================================================================
if( m_pObj->m_uRsType == PROPERTYQUALIFIER ||
m_pObj->m_uRsType == CLASSQUALIFIER )
{
hr = m_pObj->ResetQualifers(hChapter);
}
else
if(m_pObj->m_bIsChildRs == FALSE)
hr = m_pObj->ResetInstances();
if(hr == S_OK)
{
//============================================================================
// clear "end of cursor" flag
//============================================================================
m_pObj->SetStatus(hChapter, ~STAT_ENDOFCURSOR);
// if the rowset is as a result of command then set the return value to signify
// that command has been executed
// Rowset is also reopened if rowset is forward only rowset
// If Command is reexecuted , then release all the rows as the rows will not be
// valid if command is re-executed
if(!((CANSCROLLBACKWARDS & m_pObj->m_ulProps) ||
(CANFETCHBACKWARDS & m_pObj->m_ulProps) ||
(BOOKMARKPROP & m_pObj->m_ulProps)) ||
m_pObj->m_uRsType == METHOD_ROWSET)
{
m_pObj->ReleaseAllRows();
hr = DB_S_COMMANDREEXECUTED;
}
}
} // else for If ( rows are not released when CANHOLDROWS is false)
} // if ( no rows are fetched till now)
} // else if( check for validity of HCHAPTER)
hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_IRowset);
CATCH_BLOCK_HRESULT(hr,L"IRowset::RestartPosition");
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
//
// Adds a reference count to an existing row handle
//
// Returns one of the following values:
// S_OK | success
// DB_S_ERRORSOCCURRED | some elements of rghRows were invalid
// DB_E_ERRORSOCCURRED | all elements of rghRows were invalid
// E_INVALIDARG | rghRows was a NULL pointer and crow > 0
//
// NTRaid:111815
// 06/06/00
///////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CImpIRowsetLocate::AddRefRows ( DBCOUNTITEM cRows, // IN Number of rows to refcount
const HROW rghRows[], // IN Array of row handles to refcount
DBREFCOUNT rgRefCounts[], // OUT Array of refcounts
DBROWSTATUS rgRowStatus[]) // OUT Array of row status
{
HRESULT hr = S_OK;
ULONG ihRow = 0L;
ULONG cErrors = 0L;
ROWBUFF *pRowBuff = NULL;
CSetStructuredExceptionHandler seh;
TRY_BLOCK;
// Seriliaze the object
CAutoBlock cab(ROWSET->GetCriticalSection());
// clear error information
g_pCError->ClearErrorInfo();
//============================================
// If cRows is 0 do nothing and return S_OK
//============================================
if(cRows == 0)
return S_OK;
//============================================================================
// check params
//============================================================================
if ( cRows && !rghRows )
{
hr = E_INVALIDARG;
//return g_pCError->PostHResult(E_INVALIDARG,&IID_IRowset);
}
else
{
// If any rows is fetched data slotlist would have been initialized otherwise
// return invallid rows
if(!m_pObj->m_bHelperFunctionCreated)
{
for (ihRow = 0; ihRow < cRows; ihRow++)
{
if(rgRefCounts)
{
rgRefCounts[ihRow] = 0;
}
if(rgRowStatus)
{
rgRowStatus[ihRow] = DBROWSTATUS_E_INVALID;
}
}
hr = DB_E_ERRORSOCCURRED;
//return g_pCError->PostHResult(DB_E_ERRORSOCCURRED,&IID_IRowset);
}
else
{
//============================================================================
// for each of the HROWs the caller provided...
//============================================================================
for (ihRow = 0; ihRow < cRows; ihRow++){
if( rghRows[ihRow] <= 0)
{
if( rgRowStatus != NULL)
rgRowStatus[ihRow] = DBROWSTATUS_E_INVALID;
cErrors++;
continue;
}
//========================================================================
// check the row handle
//========================================================================
if(m_pObj->IsSlotSet((ULONG) rghRows[ihRow]) == S_OK)
{
if(( pRowBuff=m_pObj->GetRowBuff( rghRows[ihRow], TRUE )))
{
//=======================================================
// if row is marked as deleted then set the status
//=======================================================
if(DBROWSTATUS_E_DELETED == m_pObj->GetRowStatus(rghRows[ihRow]))
{
if ( rgRowStatus )
{
rgRowStatus[ihRow] = DBROWSTATUS_E_DELETED;
}
++cErrors;
}
else
{
//====================================================================
// bump refcount
//====================================================================
assert( pRowBuff->ulRefCount != 0 );
assert( m_pObj->m_ulRowRefCount != 0 );
++pRowBuff->ulRefCount;
++m_pObj->m_ulRowRefCount;
//====================================================================
// stuff new refcount into caller's array
//====================================================================
if ( rgRefCounts )
{
rgRefCounts[ihRow] = pRowBuff->ulRefCount;
}
if ( rgRowStatus )
{
rgRowStatus[ihRow] = DBROWSTATUS_S_OK;
}
}
}
else
{
if( rgRowStatus != NULL)
{
rgRowStatus[ihRow] = DBROWSTATUS_E_INVALID;
}
cErrors++;
continue;
}
}
else
{
if ( rgRefCounts )
{
rgRefCounts[ihRow] = 0;
}
if ( rgRowStatus )
{
rgRowStatus[ihRow] = DBROWSTATUS_E_INVALID;
}
++cErrors;
}
}
// If everything went OK except errors in rows use DB_S_ERRORSOCCURRED.
hr = cErrors ? ( cErrors < cRows ) ?
( DB_S_ERRORSOCCURRED ) :
( DB_E_ERRORSOCCURRED ) :
( S_OK );
} // Else for If( any rows are fetched till now)
} // Else for If( Validate input arguments )
CATCH_BLOCK_HRESULT(hr,L"IRowset::AddRefRows");
hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_IRowset);
return hr;
}
//////////////////////////////////////////////////////////////////////////////////////
//// IRowsetLocate Methods /////////////////////
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
// CImpIRowsetScroll::Compare
//
// Compares two bookmarks.
//
// Returns one of the following values:
// S_OK compare bookmarks succeeded,
// E_INVALIDARG one of the bookmark had 0 length or
// one of the bookmark pointer was null
// or pdwComparison was NULL,
// DB_E_BADBOOKMARK one or both of the bookmarks was a standard
// bookmark,
// DBCOMPARE_NOTCOMPARABLE The bookmarks passed are not comparable
// E_FAIL Compare failed for some other reason,
//
//////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CImpIRowsetLocate::Compare (HCHAPTER hChapter,
DBBKMARK cbBookmark1,
const BYTE * pBookmark1,
DBBKMARK cbBookmark2,
const BYTE * pBookmark2,
DBCOMPARE * pComparison)
{
HRESULT hr = S_OK;
CSetStructuredExceptionHandler seh;
TRY_BLOCK;
// Serialize the object
CAutoBlock cab(ROWSET->GetCriticalSection() );
// clear error information
g_pCError->ClearErrorInfo();
if(m_pObj->IsZoombie())
{
hr = E_UNEXPECTED;
}
else
// Are arguments valid?
if (cbBookmark1 == 0 || cbBookmark2 == 0 || pBookmark1 == NULL
|| pBookmark2 == NULL || pComparison == NULL)
{
hr = E_INVALIDARG;
// return g_pCError->PostHResult(E_INVALIDARG,&IID_IRowsetLocate);
}
else
{
*pComparison = DBCOMPARE_NE;
if ((cbBookmark1 != STD_BOOKMARKLENGTH
&& cbBookmark1 != BOOKMARKSIZE)
|| (cbBookmark2 != STD_BOOKMARKLENGTH
&& cbBookmark2 != BOOKMARKSIZE)
|| (cbBookmark1 == STD_BOOKMARKLENGTH
&& *pBookmark1 == DBBMK_INVALID)
|| (cbBookmark2 == STD_BOOKMARKLENGTH
&& *pBookmark2 == DBBMK_INVALID) )
{
hr = DB_E_BADBOOKMARK;
}
else
if (cbBookmark1 == STD_BOOKMARKLENGTH)
{
*pComparison = (cbBookmark2 == STD_BOOKMARKLENGTH && *(BYTE*)pBookmark1 == *(BYTE*)pBookmark2)
? DBCOMPARE_EQ : DBCOMPARE_NE;
}
else
if (cbBookmark1 == BOOKMARKSIZE)
{
*pComparison = (cbBookmark2 == BOOKMARKSIZE
&& *(ULONG *)pBookmark1 == *(ULONG *)pBookmark2)
? DBCOMPARE_EQ : DBCOMPARE_NE;
}
else
{
hr = DBCOMPARE_NOTCOMPARABLE;
}
} // Else for validating arguments
hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_IRowsetLocate);
CATCH_BLOCK_HRESULT(hr,L"IRowsetLocate::Compare");
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// CImpIRowsetScroll::GetRowsAt
//
// Fetches rows starting with the row specified by an offset from a bookmark.
//
// Returns one of the following values:
// S_OK Row fetching suceeded
// DB_S_ENDOFROWSET Start or End of rowset was reached during fetching
// E_INVALIDARG Arguments pcRowsObtained or prghRows was a NULL pointer,
// E_OUTOFMEMORY Fetching rows failed because of memory alloccation problem,
// E_FAIL fetching rows failed for some other reason,
// DB_E_ROWSNOTRELEASED Previous rowhandles were not release as
// required by the rowset type,
// DB_E_CANTFETCHBACKWARD cRows was negative and the rowset cannot fetch backward,
// DB_E_CANTSCROLLBACKWARD cRowsToSkip was negative and the rowset
// cannot scroll backward,
// OTHER | other result codes returned by called functions.
/////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CImpIRowsetLocate::GetRowsAt (HWATCHREGION hReserved1,
HCHAPTER hChapter,
DBBKMARK cbBookmark,
const BYTE * pBookmark,
DBROWOFFSET lRowsOffset,
DBROWCOUNT cRows,
DBCOUNTITEM * pcRowsObtained,
HROW ** prghRows)
{
HRESULT hr = S_OK;
CSetStructuredExceptionHandler seh;
TRY_BLOCK;
// Serialize the object
CAutoBlock cab(ROWSET->GetCriticalSection() );
// Clear previous Error Object for this thread
g_pCError->ClearErrorInfo();
if(m_pObj->IsZoombie())
{
hr = E_UNEXPECTED;
}
else
// Initialize pointer argument.
if (pcRowsObtained)
{
*pcRowsObtained = 0;
}
//========================================================================
// Check the HChapter is of the current rowset is valid
//========================================================================
if((m_pObj->m_bIsChildRs == TRUE && hChapter == DB_NULL_HCHAPTER) || (LONG_PTR)hChapter < 0 ||
m_pObj->m_bIsChildRs == FALSE && hChapter != 0)
{
hr = DB_E_BADCHAPTER;
//return g_pCError->PostHResult(DB_E_BADCHAPTER,&IID_IRowsetLocate);
}
else
if ( (pcRowsObtained == NULL || prghRows == NULL) || // Check validity of pointer arguments.
(cbBookmark == 0 || pBookmark == NULL)) // Is bookmark valid?
{
hr = E_INVALIDARG;
//return g_pCError->PostHResult(E_INVALIDARG, &IID_IRowsetLocate);
}
else
{
//========================================================================
// Check the rowset parameters to see if we support this request
//========================================================================
if( S_OK == (hr = CheckParameters(pcRowsObtained, lRowsOffset, cRows, prghRows)))
{
if(hChapter)
{
hr = m_pObj->CheckAndInitializeChapter(hChapter);
/* if(FAILED(hr))
return g_pCError->PostHResult(hr, &IID_IRowsetLocate);
*/ }
if(SUCCEEDED(hr))
{
// 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))
{
//========================================================================
// Are there any unreleased rows?
//========================================================================
if( ((m_pObj->m_pIAccessor->GetBitArrayPtr())->ArrayEmpty() != S_OK) && !(m_pObj->m_ulProps & CANHOLDROWS) )
{
hr = DB_E_ROWSNOTRELEASED;
//return g_pCError->PostHResult(DB_E_ROWSNOTRELEASED, &IID_IRowsetLocate);
}
else
{
// call the function to fetch rows by bookmark
hr = m_pObj->m_pRowFetchObj->FetchNextRowsByBookMark( m_pObj,
hChapter,
cbBookmark,
pBookmark,
lRowsOffset,
cRows,
pcRowsObtained,
prghRows);
} // Rows not released with CANHOLDROWS set to false
} // If succeded(hr) if CreateHelperFunction called
} // if Succeeded(hr) after initializing the chapter if any
} // If(CheckParameters())
} // Else for if validating some arguments
hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_IRowsetLocate);
CATCH_BLOCK_HRESULT(hr,L"IRowsetLocate::GetRowsAt");
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// CImpIRowsetScroll::GetRowsByBookmark
//
// Fetches rows with specified bookmarks.
//
// Returns one of the following values:
// S_OK Getting rows succeeded,
// DB_S_ERRORSOCCURRED Getting rows succeeded but there were errors
// associated with some returned rows,
// E_INVALIDARG Getting rows failed because pcRowsObtained
// or prghRows was a NULL pointer, or
// cRows was not zero and either rgcbBookmarks
// or rgpBookmarks was a NULL pointer, or
// fReturnErrors was TRUE and either pcErrors or
// prgErrors was a NULL pointer,
// E_OUTOFMEMORY Getting rows failed because memory for
// holding row handles could not be allocated,
// or memory for error structures could not
// be allocated,
// DB_E_ROWSNOTRELEASED Getting rows failed because previous rowhandles
// were not released as required by the rowset type,
// OTHER Other result codes returned by called functions.
/////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CImpIRowsetLocate::GetRowsByBookmark (HCHAPTER hChapter,
DBCOUNTITEM cRows,
const DBBKMARK rgcbBookmarks[],
const BYTE * rgpBookmarks[],
HROW rghRows[],
DBROWSTATUS rgRowStatus[])
{
HRESULT hr = S_OK;
CSetStructuredExceptionHandler seh;
TRY_BLOCK;
// Serialize the object
CAutoBlock cab(ROWSET->GetCriticalSection() );
// Clear previous Error Object for this thread
g_pCError->ClearErrorInfo();
if(m_pObj->IsZoombie())
{
hr = E_UNEXPECTED;
}
else
//===========================================================================
// No-op case always succeeds.
//===========================================================================
if ( cRows == 0 ){
hr = S_OK ;
}
else
//========================================================================
// Check the HChapter is of the current rowset is valid
//========================================================================
if((m_pObj->m_bIsChildRs == TRUE && hChapter == DB_NULL_HCHAPTER) || (LONG_PTR)hChapter < 0 ||
m_pObj->m_bIsChildRs == FALSE && hChapter != 0)
{
hr = DB_E_BADCHAPTER;
//return g_pCError->PostHResult(DB_E_BADCHAPTER,&IID_IRowsetLocate);
}
else
//===========================================================================
// This implementation doesn't support scrolling backward. if the CANFETCHBACKWARDS is false
//===========================================================================
if((LONG_PTR)cRows < 0 && !(m_pObj->m_ulProps & CANFETCHBACKWARDS) )
{
hr = DB_E_CANTFETCHBACKWARDS;
//return g_pCError->PostHResult(DB_E_CANTFETCHBACKWARDS,&IID_IRowsetLocate);
}
else
if( (rghRows == NULL) || // Check validity of pointer arguments.
(rgcbBookmarks == NULL || rgpBookmarks == NULL)) // If more than zero rows required pointers to bookmarks must be real.
{
hr = E_INVALIDARG;
//return g_pCError->PostHResult(E_INVALIDARG,&IID_IRowsetLocate);
}
else
// Must detect unreleased rows in cases when holding them over is illegal.
if (!(m_pObj->m_ulProps & CANHOLDROWS))
{
hr = DB_E_ROWSNOTRELEASED;
//return g_pCError->PostHResult(DB_E_ROWSNOTRELEASED, &IID_IRowsetLocate);
}
else
{
// Initialize the Chapters if the rowset is chaptered rowset
if(hChapter)
{
hr = m_pObj->CheckAndInitializeChapter(hChapter);
}
if(SUCCEEDED(hr))
{
// 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))
{
//========================================================================
// Are there any unreleased rows?
//========================================================================
if( ((m_pObj->m_pIAccessor->GetBitArrayPtr())->ArrayEmpty() != S_OK) && !(m_pObj->m_ulProps & CANHOLDROWS) )
{
hr = DB_E_ROWSNOTRELEASED;
// return g_pCError->PostHResult(DB_E_ROWSNOTRELEASED, &IID_IRowsetLocate);
}
else
{
hr = m_pObj->m_pRowFetchObj->FetchRowsByBookMark(m_pObj,hChapter,cRows,rgcbBookmarks,rgpBookmarks,rghRows,rgRowStatus);
}
} // if(SUCCEEDED(hr)) after calling CreateHelperFunction()
} // if(Succeeded(hr)) after initializing chapters if any
} // Else for check of parameters
hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_IRowsetLocate);
CATCH_BLOCK_HRESULT(hr,L"IRowsetLocate::GetRowsByBookMark");
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// Returns hash values for the specified bookmarks.
//
// Returns one of the following values:
// S_OK Getting hash succeeded,
// DB_S_ERRORSOCCURED At least one bookmark was successfully hashed
// but an element of rgcbBookmarks was 0, or
// an element of rgpBookmarks was null pointer, or
// an element of rgpBookmarks pointed to a
// standard bookmark,
// E_INVALIDARG cBookmarks was not 0 and rgcbBookmarks or
// rgpBookmarks was a null pointer, or
// prgHashedValues was a null pointer,
// DB_E_ERRORSOCCURED No bookmarks were successfully hashed,
// OTHER other result codes returned by called functions.
/////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CImpIRowsetLocate::Hash (HCHAPTER hChapter,
DBBKMARK cBookmarks,
const DBBKMARK rgcbBookmarks[],
const BYTE * rgpBookmarks[],
DBHASHVALUE rgHashedValues[],
DBROWSTATUS rgBookmarkStatus[])
{
ULONG iBmk, cErrors;
HRESULT hr;
CSetStructuredExceptionHandler seh;
TRY_BLOCK;
// Serialize the object
CAutoBlock cab(ROWSET->GetCriticalSection() );
// Clear previous Error Object for this thread
g_pCError->ClearErrorInfo();
if(m_pObj->IsZoombie())
{
hr = E_UNEXPECTED;
}
else
//========================================================================
// Check the HChapter is of the current rowset is valid
//========================================================================
if((m_pObj->m_bIsChildRs == TRUE && hChapter == DB_NULL_HCHAPTER) || (LONG_PTR)hChapter < 0 ||
m_pObj->m_bIsChildRs == FALSE && hChapter != 0)
{
hr = DB_E_BADCHAPTER;
//return g_pCError->PostHResult(DB_E_BADCHAPTER,&IID_IRowsetLocate);
}
else
// Check arguments
if ( (cBookmarks && (rgcbBookmarks == NULL || rgpBookmarks == NULL))
|| (rgHashedValues == NULL))
{
hr = E_INVALIDARG;
//return g_pCError->PostHResult(E_INVALIDARG, &IID_IRowsetLocate);
}
else
{
cErrors = 0;
//=================================================================
// Initialize the BookMarkStatus if valid pointer is passed
//=================================================================
if (rgBookmarkStatus)
{
for (iBmk =0; iBmk <cBookmarks; iBmk++)
rgBookmarkStatus[iBmk] = DBROWSTATUS_S_OK;
}
// Loop through the array of bookmarks hashing 'em and recording
// their status.
for (iBmk =0; iBmk <cBookmarks; iBmk++)
{
hr = m_pObj->m_pHashTblBkmark->HashBmk(rgcbBookmarks[iBmk],
rgpBookmarks[iBmk],
&(rgHashedValues[iBmk]));
if (FAILED(hr))
{
cErrors++;
if (rgBookmarkStatus)
{
rgBookmarkStatus[iBmk] = DBROWSTATUS_E_INVALID;
}
}
}
hr = cErrors
? (cErrors <cBookmarks)
? DB_S_ERRORSOCCURRED : DB_E_ERRORSOCCURRED
: S_OK;
} // Else for Validating arguments
hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_IRowsetLocate);
CATCH_BLOCK_HRESULT(hr,L"IRowsetLocate::Hash");
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
// Check the input parameters
///////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CImpIRowsetLocate::CheckParameters(DBCOUNTITEM * pcRowsObtained, DBROWOFFSET lRowOffset, DBROWCOUNT cRows,HROW **prghRows )
{
HRESULT hr = S_OK;
//===========================================================================
// init out-params
//===========================================================================
if ( pcRowsObtained ){
*pcRowsObtained = 0;
}
//===========================================================================
// Check validity of arguments.
//===========================================================================
if ( pcRowsObtained == NULL || prghRows == NULL )
{
hr = E_INVALIDARG;
//return E_INVALIDARG ;
}
else
//===========================================================================
// No-op case always succeeds.
//===========================================================================
if ( cRows == 0 )
{
hr = S_OK;
//return S_OK ;
}
else
//===========================================================================
// This implementation doesn't support scrolling backward. if the CANFETCHBACKWARDS is false
//===========================================================================
if((LONG_PTR)cRows < 0 && !(m_pObj->m_ulProps & CANFETCHBACKWARDS) )
{
hr = DB_E_CANTFETCHBACKWARDS;
//return DB_E_CANTFETCHBACKWARDS ;
}
else
//===========================================================================
// This implementation doesn't support scrolling backward.if the CANTSCROLLBACKWARDS is false
//===========================================================================
if ( lRowOffset < 0 && !(m_pObj->m_ulProps & CANSCROLLBACKWARDS) )
{
hr = DB_E_CANTSCROLLBACKWARDS;
//return DB_E_CANTSCROLLBACKWARDS ;
}
//===========================================================================
// return success
//===========================================================================
return hr;
}