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

357 lines
10 KiB
C++

///////////////////////////////////////////////////////////////////////////////////////////
//
// Microsoft WMIOLE DB Provider
// (C) Copyright 1999 Microsoft Corporation. All Rights Reserved.
//
// IRowsetIdentity interface implementation
//
///////////////////////////////////////////////////////////////////////////////////////////
#include "headers.h"
///////////////////////////////////////////////////////////////////////////////////////////
//
// Compares two row handles to see if they refer to the same row instance.
//
// HRESULT
// S_FALSE Method Succeeded but did not refer to the same row
// S_OK Method Succeeded
// DB_E_BADROWHANDLE Invalid row handle given
// OTHER Other HRESULTs returned by called functions
//
///////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CImplIRowsetRefresh::GetLastVisibleData(HROW hRow,HACCESSOR hAccessor,void * pData)
{
//============================================================
// Call this function of RowFetch Object to fetch data
//============================================================
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
{
hr = m_pObj->m_pRowFetchObj->FetchData(m_pObj,hRow,hAccessor,pData);
}
hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_IRowsetRefresh);
CATCH_BLOCK_HRESULT(hr,L"IRowsetRefresh::GetLastVisibleData");
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////////
//
// Compares two row handles to see if they refer to the same row instance.
//
// HRESULT
// S_FALSE Method Succeeded but did not refer to the same row
// S_OK Method Succeeded
// DB_E_BADROWHANDLE Invalid row handle given
// DB_E_BADCHAPTER Bad HCHAPTER
// E_INVALIDARG One of the parameters is invalid
// OTHER Other HRESULTs returned by called functions
//
// NTRaid 111830 (Raid about CRowset::GetData Found that this function is not returning
// the proper error while looking into this
// NTRaid 147095
///////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CImplIRowsetRefresh::RefreshVisibleData(HCHAPTER hChapter,
DBCOUNTITEM cRows,
const HROW rghRows[],
BOOL fOverwrite,
DBCOUNTITEM * pcRowsRefreshed,
HROW ** prghRowsRefreshed,
DBROWSTATUS ** prgRowStatus)
{
HRESULT hr = S_OK;
DBCOUNTITEM lRowsRefreshed = 0;
DBROWSTATUS * rgRowStatus;
HROW * prghRows = NULL;
BOOL bGetAllActiveRows = FALSE;
BSTR strBookMark = Wmioledb_SysAllocString(NULL);
CSetStructuredExceptionHandler seh;
TRY_BLOCK;
// Seriliaze the object
CAutoBlock cab(ROWSET->GetCriticalSection());
// Clear Error information
g_pCError->ClearErrorInfo();
*prgRowStatus = NULL;
if(m_pObj->IsZoombie())
{
hr = E_UNEXPECTED;
}
else
//========================================================================
// Check the HChapter is of the current rowset if it is non zero
//========================================================================
if((LONG_PTR) cRows < 0 || ( cRows > 0 && rghRows == NULL) ||
(pcRowsRefreshed == NULL && prghRowsRefreshed != NULL) )
{
hr = E_INVALIDARG;
}
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;
}
else
{
try
{
if(prghRowsRefreshed)
{
*prghRowsRefreshed = NULL;
}
if(pcRowsRefreshed)
{
*pcRowsRefreshed = 0;
}
if(prgRowStatus)
{
*prgRowStatus = NULL;
}
// If cRows is zero get all the active rows
if(cRows == 0)
{
bGetAllActiveRows = TRUE;
//=================================================
// if the rowset is child rowset get the list
// open rowset from the chapter manager
//=================================================
if(m_pObj->m_bIsChildRs)
{
hr = m_pObj->m_pChapterMgr->GetAllHROWs(prghRows,cRows);
}
//=========================================
// else get it from the instance manager
//=========================================
else
{
hr = m_pObj->m_InstMgr->GetAllHROWs(prghRows,cRows);
}
}
else
{
prghRows = (HROW *)&rghRows[0];
}
// allocate memory for the row status
rgRowStatus = (DBROWSTATUS *)g_pIMalloc->Alloc(sizeof(DBROWSTATUS) * cRows);
if(S_OK == CheckIfRowsExists(cRows,prghRows,rgRowStatus))
{
// Navigate thru each row
for( ULONG nIndex = 0 ; nIndex < cRows ; nIndex++)
{
// If the status of the row is ok then refresh the instance
if(rgRowStatus[nIndex] == DBROWSTATUS_S_OK)
{
// call this function to refresh the instance pointer
m_pObj->RefreshInstance(m_pObj->GetInstancePtr(prghRows[nIndex]));
if(m_pObj->m_uRsType == PROPERTYQUALIFIER ||
m_pObj->m_uRsType == CLASSQUALIFIER )
{
m_pObj->GetQualiferName(prghRows[nIndex],strBookMark);
}
// Release the previous row data
hr = m_pObj->ReleaseRowData(prghRows[nIndex],FALSE); // don't release the slots
if (FAILED(hr))
{
rgRowStatus[nIndex] = DBROWSTATUS_E_FAIL;
}
//===================================================================
// if data otherupdatedelete property is false then get the data
// for the row,
// Get the data even if rowset is pointing to a qualifer rowset
//===================================================================
// Get the data for the current row
hr = m_pObj->GetData(prghRows[nIndex],strBookMark);
if(FAILED(hr))
{
rgRowStatus[nIndex] = DBROWSTATUS_E_FAIL;
}
else
{
m_pObj->m_ulLastFetchedRow = prghRows[nIndex];
lRowsRefreshed++;
rgRowStatus[nIndex] = DBROWSTATUS_S_OK;
}
}
if(strBookMark != NULL)
{
SysFreeString(strBookMark);
strBookMark = NULL;
}
hr = S_OK;
}
// Allocate memory for output HROW and ROWSTATUS
if(pcRowsRefreshed)
{
*prghRowsRefreshed = (HROW *)g_pIMalloc->Alloc(sizeof(HROW) * cRows);
if(*prghRowsRefreshed)
{
memcpy( *prghRowsRefreshed,prghRows,sizeof(HROW) * cRows);
*pcRowsRefreshed = lRowsRefreshed;
}
else
{
hr = E_OUTOFMEMORY;
}
if(SUCCEEDED(hr) && prgRowStatus)
{
*prgRowStatus = (DBROWSTATUS *)g_pIMalloc->Alloc(sizeof(DBROWSTATUS) * cRows);
if(*prgRowStatus)
{
memcpy( *prgRowStatus,rgRowStatus,sizeof(DBROWSTATUS) * cRows);
}
else
{
if(*prghRowsRefreshed != NULL)
{
g_pIMalloc->Free(*prghRowsRefreshed);
}
*prghRowsRefreshed = NULL;
*pcRowsRefreshed = 0;
hr = E_OUTOFMEMORY;
}
}
}
// free the temporarily allocated memory
g_pIMalloc->Free(rgRowStatus);
// free the memory if allocated by GetAllHROWs
// which is called when cRows is 0
if(prghRows != NULL && bGetAllActiveRows == TRUE)
{
SAFE_DELETE_ARRAY(prghRows);
}
}
else
{
hr = E_FAIL;
}
}
catch(...)
{
if(rgRowStatus != NULL)
g_pIMalloc->Free(rgRowStatus);
if(*prgRowStatus != NULL)
g_pIMalloc->Free(*prgRowStatus);
if(*prghRowsRefreshed != NULL)
g_pIMalloc->Free(*prghRowsRefreshed);
if(prghRows != NULL && rghRows == NULL)
{
SAFE_DELETE_ARRAY(prghRows);
}
throw;
}
}
if(SUCCEEDED(hr))
{
if(lRowsRefreshed == 0 && cRows)
{
hr = DB_E_ERRORSOCCURRED;
}
else
{
hr = cRows>lRowsRefreshed ? DB_S_ERRORSOCCURRED : S_OK;
}
}
hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_IRowsetRefresh);
CATCH_BLOCK_HRESULT(hr,L"IRowsetRefresh::RefreshVisibleData");
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Function to check the row handles and set the status of the row handles
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CImplIRowsetRefresh::CheckIfRowsExists(DBCOUNTITEM cRows,const HROW rghRows[],DBROWSTATUS * prgRowStatus)
{
HRESULT hr = S_OK;
DBSTATUS dwStatus = 0;
if (!m_pObj->BitArrayInitialized()){
//=================================================================================
// This is the case when the method was called even before the rowset got fully
// intialized, hence no rows could have been fetched yet, therefore there do not
// exist valid row handles, and all row handles provided must be invalid.
//=================================================================================
hr = DB_E_BADROWHANDLE;
}
else
{
for ( ULONG nIndex = 0 ; nIndex < cRows ; nIndex++)
{
//=================================================================================
// Check validity of input handles
//=================================================================================
if(TRUE == m_pObj->IsRowExists(rghRows[nIndex]) )
{
dwStatus = m_pObj->GetRowStatus(rghRows[nIndex]);
if( dwStatus != DBROWSTATUS_S_OK )
{
if(dwStatus == DBROWSTATUS_E_DELETED ||
dwStatus == DBROWSTATUS_E_DELETED)
hr = DB_E_DELETEDROW;
else
prgRowStatus[nIndex] = DBROWSTATUS_E_FAIL;
}
else
prgRowStatus[nIndex] = DBROWSTATUS_S_OK;
}
else
{
prgRowStatus[nIndex] = DBROWSTATUS_E_INVALID;
}
}
}
return hr;
}