1191 lines
38 KiB
C++
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;
|
|
}
|