/////////////////////////////////////////////////////////////////////////// // // 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 m_pHashTblBkmark->HashBmk(rgcbBookmarks[iBmk], rgpBookmarks[iBmk], &(rgHashedValues[iBmk])); if (FAILED(hr)) { cErrors++; if (rgBookmarkStatus) { rgBookmarkStatus[iBmk] = DBROWSTATUS_E_INVALID; } } } hr = cErrors ? (cErrors 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; }