1072 lines
36 KiB
C++
1072 lines
36 KiB
C++
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Microsoft WMI OLE DB Provider
|
|
// (C) Copyright 1999 Microsoft Corporation. All Rights Reserved.
|
|
//
|
|
// COMMAND.CPP - CCommand object implementation
|
|
// File also contain the implementation of CQuery class
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "headers.h"
|
|
#include "command.h"
|
|
|
|
#define NO_ROWCOUNT_TOTAL (-1)
|
|
#define PARAM_LIST_SIZE 2056
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
#pragma warning (disable:4355)
|
|
CCommand::CCommand( CDBSession* pCDBSession, LPUNKNOWN pUnkOuter ) : CBaseObj(BOT_COMMAND,pUnkOuter)
|
|
{
|
|
//===============================================================
|
|
// Initially, NULL all contained interfaces
|
|
//===============================================================
|
|
m_pIAccessor = NULL;
|
|
m_pIColumnsInfo = NULL;
|
|
m_pIConvertType = NULL;
|
|
|
|
|
|
//=======================================================
|
|
// Establish the parent object
|
|
//=======================================================
|
|
m_pCDBSession = pCDBSession;
|
|
m_pCDBSession->GetOuterUnknown()->AddRef();
|
|
|
|
//=======================================================
|
|
// Initialize all ptrs to embedded interfaces
|
|
//=======================================================
|
|
m_pICommandText = NULL;
|
|
m_pICommandWithParameters = NULL;
|
|
m_pICommandProperties = NULL;
|
|
m_pISupportErrorInfo = NULL;
|
|
|
|
|
|
//=======================================================
|
|
// Initialize simple member vars
|
|
//=======================================================
|
|
m_cRowsetsOpen = 0;
|
|
m_guidImpersonate = GUID_NULL;
|
|
// m_pdbc = pCDBSession->GetDBConnection();
|
|
m_pQuery = NULL;
|
|
|
|
m_pColumns = NULL;
|
|
m_cTotalCols = 0;
|
|
m_cCols = 0;
|
|
m_cNestedCols = 0;
|
|
|
|
}
|
|
#pragma warning (default:4355)
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Destructor for this class
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
CCommand::~CCommand (void)
|
|
{
|
|
|
|
SAFE_DELETE_PTR( m_pUtilProps);
|
|
SAFE_DELETE_PTR( m_pQuery );
|
|
//====================================================================
|
|
// Free Statement
|
|
//====================================================================
|
|
if (m_pQuery)
|
|
{
|
|
m_pQuery->InitQuery();
|
|
}
|
|
|
|
//=======================================================
|
|
// Delete the embedded pointers
|
|
//=======================================================
|
|
SAFE_DELETE_PTR( m_pICommandText );
|
|
SAFE_DELETE_PTR( m_pICommandWithParameters );
|
|
SAFE_DELETE_PTR( m_pICommandProperties );
|
|
SAFE_DELETE_PTR(m_pIAccessor);
|
|
SAFE_DELETE_PTR(m_pIConvertType);
|
|
SAFE_DELETE_PTR(m_pISupportErrorInfo);
|
|
SAFE_DELETE_PTR(m_pIColumnsInfo);
|
|
|
|
|
|
SAFE_DELETE_PTR(m_pColumns);
|
|
|
|
//====================================================================
|
|
// Since Command Object is going away, we can decrement
|
|
// our count on the session object.
|
|
// Note that this typically deletes our hdbc, DataSource, Session.
|
|
// (So do this last.)
|
|
//====================================================================
|
|
if (m_pCDBSession)
|
|
{
|
|
m_pCDBSession->GetOuterUnknown()->Release();
|
|
}
|
|
}
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Initialize the command Object. This Init routine should be used by CreateCommand and also be called
|
|
// as a secondary initialization routine for the other FInit on the command object.
|
|
//
|
|
// If this initialization routine fails, it is the callers responsibility to delete this object.
|
|
// The destructor will then clean up any allocated resources
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CCommand::FInit( WORD wRowsetProps )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
//===============================================
|
|
// Get the query class going
|
|
//===============================================
|
|
m_pQuery = new CQuery;
|
|
|
|
//===============================================
|
|
// Initialize rowset properties
|
|
//===============================================
|
|
m_pUtilProps = new CUtilProp;
|
|
|
|
// NTRaid: 136443
|
|
// 07/05/00
|
|
if(m_pUtilProps == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
if(SUCCEEDED(hr = m_pUtilProps->FInit(COMMANDPROP)))
|
|
{
|
|
|
|
//===============================================
|
|
// Initialize ErrorData
|
|
//===============================================
|
|
if (FAILED(m_CError.FInit()))
|
|
hr = (E_OUTOFMEMORY);
|
|
else
|
|
{
|
|
m_pIAccessor = new CImpIAccessor(this,FALSE);
|
|
if( m_pIAccessor ){
|
|
hr = m_pIAccessor->FInit();
|
|
|
|
}
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
m_pICommandText = new CImpICommandText(this);
|
|
m_pICommandWithParameters = new CImpICommandWithParameters(this);
|
|
m_pICommandProperties = new CImpICommandProperties(this);
|
|
m_pIConvertType = new CImpIConvertType(this);
|
|
m_pISupportErrorInfo = new CImpISupportErrorInfo(this);
|
|
m_pIColumnsInfo = new CImpIColumnsInfoCmd(this);
|
|
|
|
//===============================================
|
|
// Initialize name pool
|
|
//===============================================
|
|
m_extNamePool.FInit(1,0,256);
|
|
|
|
|
|
if( m_pUtilProps && m_pIAccessor && m_pICommandText && m_pICommandWithParameters &&
|
|
m_pIConvertType && m_pIColumnsInfo && m_pISupportErrorInfo)
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = AddInterfacesForISupportErrorInfo();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Function to add interfaces to ISupportErrorInfo interface
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CCommand::AddInterfacesForISupportErrorInfo()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if(SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_IAccessor)) &&
|
|
SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_ICommand)) &&
|
|
SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_ICommandText)) &&
|
|
SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_ICommandProperties)) &&
|
|
SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_ICommandWithParameters)) &&
|
|
SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_IColumnsInfo)))
|
|
{
|
|
hr = m_pISupportErrorInfo->AddInterfaceID(IID_IConvertType);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Determines if command is canceled and if not sets the currently active CQuery.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
inline HRESULT CCommand::CheckCanceledHelper(CQuery* pstmt)
|
|
{
|
|
HRESULT hr;
|
|
DWORD dwCancelStatus = m_pQuery->GetCancelStatus();
|
|
|
|
// Set the currently active CQuery, for use by the cancel routine
|
|
m_pQuery->m_pcsQuery->Enter();
|
|
if (dwCancelStatus & CMD_EXEC_CANCELED){
|
|
dwCancelStatus &= ~(CMD_EXEC_CANCELED|CMD_EXEC_CANCELED_BEFORE_CQUERY_SET);
|
|
hr = DB_E_CANCELED;
|
|
}
|
|
else{
|
|
hr = S_OK;
|
|
}
|
|
m_pQuery->m_pcsQuery->Leave();
|
|
return hr;
|
|
}
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Returns a pointer to a specified interface. Callers use QueryInterface to determine which interfaces
|
|
// the called object supports.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP CCommand::QueryInterface( REFIID riid, LPVOID * ppv )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if ( ppv == NULL )
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
//=======================================================
|
|
// This is the non-delegating IUnknown implementation
|
|
//=======================================================
|
|
if ( riid == IID_IUnknown )
|
|
*ppv = (LPVOID)this;
|
|
else if ( riid == IID_IAccessor )
|
|
*ppv = (LPVOID)m_pIAccessor;
|
|
else if ( riid == IID_ICommand || riid == IID_ICommandText)
|
|
*ppv = (LPVOID)m_pICommandText;
|
|
else if ( riid == IID_ICommandProperties )
|
|
*ppv = (LPVOID)m_pICommandProperties;
|
|
else if ( riid == IID_IColumnsInfo )
|
|
*ppv = (LPVOID)m_pIColumnsInfo;
|
|
else if ( riid == IID_ICommandWithParameters )
|
|
*ppv = (LPVOID)m_pICommandWithParameters;
|
|
else if ( riid == IID_ISupportErrorInfo )
|
|
*ppv = (LPVOID)m_pISupportErrorInfo;
|
|
else if ( riid == IID_IConvertType )
|
|
*ppv = (LPVOID)m_pIConvertType;
|
|
else{
|
|
*ppv = NULL;
|
|
hr = E_NOINTERFACE;
|
|
}
|
|
|
|
if( *ppv ){
|
|
((LPUNKNOWN)*ppv)->AddRef();
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Increments a persistence count for the object
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP_(ULONG) CCommand::AddRef (void)
|
|
{
|
|
ULONG cRef = InterlockedIncrement( (long*) &m_cRef);
|
|
return cRef;
|
|
}
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Decrements a persistence count for the object and if persistence count is 0, the object destroys itself.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP_(ULONG) CCommand::Release (void)
|
|
{
|
|
ULONG cRef = InterlockedDecrement( (long *) &m_cRef);
|
|
if ( !cRef ){
|
|
delete this;
|
|
return 0;
|
|
}
|
|
return cRef;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// UTILITY FUNCTIONS UTILITY FUNCTIONS
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Errors that can occur may result in another HRESULT other than E_FAIL, thus this routine
|
|
// determines that HRESULT and posts the errors
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CCommand::PostExecuteWarnings( CErrorData* pError, const IID* piid )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (*piid == IID_ITableDefinition){
|
|
|
|
}
|
|
if (*piid == IID_IIndexDefinition){
|
|
}
|
|
//==========================================================
|
|
// If we are not posting errors for IID_IOpenRowset
|
|
//==========================================================
|
|
if (*piid == IID_IOpenRowset){
|
|
//======================================================
|
|
// Map errors in command to DB_E_NOTABLE.
|
|
// Other errors should flow through. (Some like
|
|
// _DATAOVERFLOW we should never get.)
|
|
//======================================================
|
|
if (hr == DB_E_ERRORSINCOMMAND)
|
|
{
|
|
hr = (DB_E_NOTABLE);
|
|
}
|
|
else if (hr == DB_E_ABORTLIMITREACHED || hr == DB_E_CANCELED)
|
|
{
|
|
hr = (E_FAIL);
|
|
}
|
|
}
|
|
g_pCError->PostWMIErrors(hr, piid, pError);
|
|
return hr;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Errors that can occur may result in another HRESULT other than E_FAIL, thus this routine
|
|
// determines that HRESULT and posts the errors
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CCommand::PostExecuteErrors( CErrorData* pError, const IID* piid )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (*piid == IID_ITableDefinition){
|
|
|
|
}
|
|
if (*piid == IID_IIndexDefinition){
|
|
}
|
|
//==========================================================
|
|
// If we are not posting errors for IID_IOpenRowset
|
|
//==========================================================
|
|
if (*piid == IID_IOpenRowset){
|
|
//======================================================
|
|
// Map errors in command to DB_E_NOTABLE.
|
|
// Other errors should flow through. (Some like
|
|
// _DATAOVERFLOW we should never get.)
|
|
//======================================================
|
|
if (hr == DB_E_ERRORSINCOMMAND)
|
|
{
|
|
hr = (DB_E_NOTABLE);
|
|
}
|
|
else if (hr == DB_E_ABORTLIMITREACHED || hr == DB_E_CANCELED)
|
|
{
|
|
hr = (E_FAIL);
|
|
}
|
|
}
|
|
g_pCError->PostWMIErrors(hr, piid, pError);
|
|
return hr;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Marks command as unprepared, and may force this state.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP CCommand::UnprepareHelper( DWORD dwUnprepareType )
|
|
{
|
|
|
|
// Unprepare the statement - free it from WBEM
|
|
|
|
|
|
// Free memory for the row metadata for the first rowset in the command.
|
|
// m_extNamePool.Free();
|
|
DWORD dwStatus = m_pQuery->GetStatus();
|
|
|
|
dwStatus &= ~CMD_HAVE_COLUMNINFO;
|
|
|
|
if (UNPREPARE_NEW_CMD == dwUnprepareType) // A new command is being set
|
|
{
|
|
// We need to remember that we have to rebuild our parameter info
|
|
dwStatus &= ~(CMD_TEXT_PARSED
|
|
| CMD_READY
|
|
| CMD_PARAMS_USED
|
|
| CMD_EXECUTED_ONCE );
|
|
|
|
// Reset parameter information.
|
|
if (m_pQuery->GetParamCount()){
|
|
if (m_pQuery->m_prgbCallParams){
|
|
delete [] m_pQuery->m_prgbCallParams;
|
|
m_pQuery->m_prgbCallParams = NULL;
|
|
}
|
|
if (m_pQuery->m_prgProviderParamInfo){
|
|
delete [] m_pQuery->m_prgProviderParamInfo;
|
|
m_pQuery->m_prgProviderParamInfo = NULL;
|
|
}
|
|
//@devnote We do not delete the consumer parameter information.
|
|
// The only reference in the OLE DB spec to removing the consumer
|
|
// parameter info is via ICommandWithParameters::SetParameterInfo.
|
|
}
|
|
}
|
|
else if (UNPREPARE_RESET_CMD == dwUnprepareType){
|
|
dwStatus &= ~CMD_READY;
|
|
}
|
|
|
|
m_pQuery->InitStatus(dwStatus);
|
|
return S_OK;
|
|
}
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Determines if bookmarks are present.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
BOOL CCommand::FHaveBookmarks()
|
|
{
|
|
BOOL flag = FALSE;
|
|
|
|
// flag = (m_pUtilProps.IsRequiredTrue(CUtilProp::eid_DBPROPSET_ROWSET, CUtilProp::eid_DBPROPVAL_BOOKMARKS)
|
|
// || m_pUtilProps.IsRequiredTrue(CUtilProp::eid_DBPROPSET_ROWSET, CUtilProp::eid_DBPROPVAL_IRowsetLocate)
|
|
// || m_pUtilProps.IsRequiredTrue(CUtilProp::eid_DBPROPSET_ROWSET, CUtilProp::eid_DBPROPVAL_CANHOLDROWS) );
|
|
return flag;
|
|
}
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Re-executes a command to reposition to reposition to the beginning of the rowset.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CCommand::ReExecute( PCROWSET pCRowset,LONG* pcCursorRows, WORD* pcCols )
|
|
{
|
|
DWORD dwFlags = EXECUTE_RESTART;
|
|
// return ExecuteHelper(&IID_IRowset, pCRowset->GetStmt(), &dwFlags, pCRowset->GetRowsetProps(), NULL, NULL, pcCursorRows, pcCols, NULL);
|
|
return S_OK;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP CCommand::Execute( IUnknown* pUnkOuter, //@parm IN | Outer Unknown
|
|
REFIID riid, //@parm IN | Interface ID of the interface being queried for.
|
|
DBPARAMS* pParams, //@parm INOUT | Parameter Array
|
|
DBROWCOUNT* pcRowsAffected, //@parm OUT | count of rows affected by command
|
|
IUnknown** ppRowsets //@parm OUT | Pointer to interface that was instantiated
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
HRESULT hrProp = S_OK;
|
|
DWORD dwFlags = 0;
|
|
CRowset* pCRowset = NULL;
|
|
DWORD dwStatus = 0;
|
|
LPWSTR pwstrWQL = NULL;
|
|
ULONG cwchWQL = 0;
|
|
const IID* pIID = &IID_ICommand;
|
|
CUtilProp* pRowsetProps = NULL;
|
|
CUtlParam *pCUtlParam = NULL;
|
|
LONG cCursorCount = 0;
|
|
|
|
//==========================================================================
|
|
// Initialize Return Buffers
|
|
//==========================================================================
|
|
if ( ppRowsets )
|
|
{
|
|
*ppRowsets = NULL;
|
|
}
|
|
if ( pcRowsAffected )
|
|
{
|
|
*pcRowsAffected = NO_ROWCOUNT_TOTAL;
|
|
}
|
|
|
|
|
|
//==========================================================================
|
|
// If the IID asked for is IID_NULL, then we can expect that this is a
|
|
// non-row returning statement
|
|
//==========================================================================
|
|
if (riid == IID_NULL)
|
|
{
|
|
dwFlags |= EXECUTE_NOROWSET;
|
|
}
|
|
|
|
//==========================================================================
|
|
// Check to see if IID_IOpenRowset is calling Execute to open a rowset.
|
|
//==========================================================================
|
|
if (m_guidImpersonate != GUID_NULL)
|
|
{
|
|
pIID = &m_guidImpersonate;
|
|
}
|
|
|
|
//==========================================================================
|
|
// Check Arguments - Only check on row returning statements
|
|
//==========================================================================
|
|
if (!(dwFlags & EXECUTE_NOROWSET) && (ppRowsets == NULL))
|
|
{
|
|
hr = E_INVALIDARG;
|
|
// return g_pCError->PostHResult((E_INVALIDARG), pIID);
|
|
}
|
|
else
|
|
//==========================================================================
|
|
// At least 1 ParamSet and pData is null
|
|
//==========================================================================
|
|
if (pParams && (pParams->cParamSets > 0) && (NULL == pParams->pData))
|
|
{
|
|
hr = E_INVALIDARG;
|
|
// return g_pCError->PostHResult((E_INVALIDARG), pIID);
|
|
}
|
|
else
|
|
//==========================================================================
|
|
// Check that a command has been set
|
|
//==========================================================================
|
|
if(!(m_pQuery->GetStatus() & CMD_TEXT_SET))
|
|
{
|
|
hr = DB_E_NOCOMMAND;
|
|
// return g_pCError->PostHResult((DB_E_NOCOMMAND), pIID);
|
|
}
|
|
else
|
|
//==========================================================================
|
|
// The outer object must explicitly ask for IUnknown
|
|
//==========================================================================
|
|
if (pUnkOuter != NULL && riid != IID_IUnknown)
|
|
{
|
|
hr = DB_E_NOAGGREGATION;
|
|
// return g_pCError->PostHResult((DB_E_NOAGGREGATION), pIID);
|
|
}
|
|
else
|
|
{
|
|
//==========================================================================
|
|
// If there are parameters
|
|
//==========================================================================
|
|
if (pParams){
|
|
|
|
//======================================================================
|
|
// Build the bind information
|
|
//======================================================================
|
|
pCUtlParam = new CUtlParam;
|
|
if (NULL == pCUtlParam){
|
|
hr = E_OUTOFMEMORY;
|
|
// hr = g_pCError->PostHResult((E_OUTOFMEMORY), pIID);
|
|
}
|
|
else
|
|
{
|
|
pCUtlParam->AddRef();
|
|
hr = pCUtlParam->BuildBindInfo(this, pParams, pIID);
|
|
/* if (SUCCEEDED(hr = pCUtlParam->BuildBindInfo(this, pParams, pIID)))
|
|
{
|
|
m_pQuery->SetType(METHOD_ROWSET);
|
|
}
|
|
|
|
*/ }
|
|
}
|
|
|
|
if( SUCCEEDED(hr))
|
|
{
|
|
if (!(m_pQuery->GetStatus() & CMD_EXECUTED_ONCE)){
|
|
//======================================================================
|
|
// Set the parameter binding information for the statement
|
|
//======================================================================
|
|
if (pCUtlParam)
|
|
{
|
|
m_pQuery->SetBindInfo(pCUtlParam);
|
|
}
|
|
|
|
//======================================================================
|
|
// If command not prepared, prepare it now
|
|
//======================================================================
|
|
m_pQuery->SetStatus(CMD_READY);
|
|
}
|
|
|
|
//==========================================================================
|
|
// For Row Returning statements, we need to make a copy of the
|
|
// command object's Property object to hand off to the Rowset Object
|
|
//==========================================================================
|
|
|
|
if ( !(dwFlags & EXECUTE_NOROWSET) ){
|
|
|
|
|
|
pCRowset = new CRowset(pUnkOuter,m_pCDBSession);
|
|
if (pCRowset == NULL){
|
|
hr = E_OUTOFMEMORY;
|
|
// hr = g_pCError->PostHResult((E_OUTOFMEMORY), pIID);
|
|
}
|
|
else
|
|
{
|
|
//=========================================================================
|
|
// We need to take a reference count on the pCRowset Ptr so if a
|
|
// called method calls Addref and then Release on this
|
|
// pointer, we do not go back to zero and delete ourselve.
|
|
//=========================================================================
|
|
pCRowset->AddRef();
|
|
|
|
/*
|
|
//=========================================================================
|
|
// AddRef Session Object
|
|
//=========================================================================
|
|
if (m_pCDBSession)
|
|
m_pCDBSession->AddRef(); // AddRef is not required as the Rowset Constuctor
|
|
// does the AddRef on the passed session
|
|
*/
|
|
|
|
|
|
if (IID_ICommand == *pIID){
|
|
|
|
//=====================================================================
|
|
// AddRef ourself (as Parent)
|
|
//=====================================================================
|
|
// GetOuterUnknown()->AddRef();
|
|
}
|
|
else{
|
|
//=====================================================================
|
|
// AddRef Session Object (as Parent)
|
|
//=====================================================================
|
|
if (m_pCDBSession)
|
|
{
|
|
m_pCDBSession->GetOuterUnknown()->AddRef();
|
|
}
|
|
}
|
|
//=========================================================================
|
|
// AddRef ourself (as Command)
|
|
//=========================================================================
|
|
//AddRef();
|
|
|
|
//=========================================================================
|
|
// Do initialization.
|
|
//=========================================================================
|
|
ULONG cPropSets = 0;
|
|
DBPROPSET* prgPropertySets = NULL;
|
|
DBPROPIDSET rgPropIDSet[2];
|
|
DBPROPID rgPropId[1];
|
|
|
|
memset(rgPropIDSet,0,2 * sizeof(DBPROPIDSET));
|
|
// Get the property DBPROP_WMIOLEDB_ISMETHOD
|
|
rgPropId[0] = DBPROP_WMIOLEDB_ISMETHOD;
|
|
rgPropIDSet[0].cPropertyIDs = 1;
|
|
rgPropIDSet[0].guidPropertySet = DBPROPSET_WMIOLEDB_ROWSET;
|
|
rgPropIDSet[0].rgPropertyIDs = rgPropId;
|
|
|
|
// if this property is true then set the command type to METHOD
|
|
if(SUCCEEDED(hr = m_pUtilProps->GetProperties(PROPSET_COMMAND,1,rgPropIDSet, &cPropSets,&prgPropertySets)))
|
|
{
|
|
if(prgPropertySets->rgProperties->vValue.boolVal == VARIANT_TRUE)
|
|
{
|
|
m_pQuery->SetType(METHOD_ROWSET);
|
|
}
|
|
else
|
|
{
|
|
m_pQuery->SetType(COMMAND_ROWSET);
|
|
}
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
//==========================================================================
|
|
// Free memory we allocated to by GetProperties
|
|
//==========================================================================
|
|
m_pUtilProps->m_PropMemMgr.FreeDBPROPSET( cPropSets, prgPropertySets);
|
|
|
|
memset(rgPropIDSet,0,2 * sizeof(DBPROPIDSET));
|
|
|
|
// NTRaid: 135246
|
|
// Getting only the rowset properties
|
|
rgPropIDSet[0].cPropertyIDs = 0;
|
|
rgPropIDSet[0].guidPropertySet = DBPROPSET_ROWSET;
|
|
rgPropIDSet[0].rgPropertyIDs = NULL;
|
|
|
|
rgPropIDSet[1].cPropertyIDs = 0;
|
|
rgPropIDSet[1].guidPropertySet = DBPROPSET_WMIOLEDB_ROWSET;
|
|
rgPropIDSet[1].rgPropertyIDs = NULL;
|
|
|
|
//=========================================================================
|
|
// Get the properties- get the rowset properties
|
|
//=========================================================================
|
|
hr = m_pUtilProps->GetProperties(PROPSET_ROWSET,2,rgPropIDSet, &cPropSets,&prgPropertySets);
|
|
if( hr == S_OK ){
|
|
|
|
hr = pCRowset->InitRowset(cPropSets, prgPropertySets,-1,m_pQuery , this );
|
|
if ( FAILED(hr) ){
|
|
g_pCError->PostHResult(hr, pIID);
|
|
*ppRowsets = NULL;
|
|
}
|
|
|
|
}
|
|
else{
|
|
if ( FAILED(hr) ){
|
|
g_pCError->PostHResult(hr, pIID);
|
|
*ppRowsets = NULL;
|
|
}
|
|
}
|
|
|
|
if (DB_S_ERRORSOCCURRED == hr){
|
|
hrProp = DB_S_ERRORSOCCURRED;
|
|
}
|
|
|
|
//==========================================================================
|
|
// Free memory we allocated to by GetProperties
|
|
//==========================================================================
|
|
m_pUtilProps->m_PropMemMgr.FreeDBPROPSET( cPropSets, prgPropertySets);
|
|
|
|
//=========================================================================
|
|
// We are guaranteed to have handed off the pRowsetProps value,
|
|
// so set the NULL it flag
|
|
//=========================================================================
|
|
dwFlags |= EXECUTE_NULL_PROWSETPROPS;
|
|
|
|
} // Else for failure of allocation of CRowset
|
|
}
|
|
else
|
|
{
|
|
// 07/12/2000
|
|
// Modified after finding NTBug : 142348, debugging of which
|
|
// revealed that nothing was being done if a query is to be
|
|
// executed without requiring a resultant rowset
|
|
// Just execute the query here, without worring about
|
|
// building the resulting rowset
|
|
hr = m_pCDBSession->ExecuteQuery(m_pQuery);
|
|
}
|
|
|
|
if (!FAILED(hr))
|
|
{
|
|
|
|
//=========================================================================
|
|
// We are guarunteed to have handed off the pRowsetProps value, so set
|
|
// the NULL it flag
|
|
//=========================================================================
|
|
dwFlags |= EXECUTE_NULL_PROWSETPROPS;
|
|
|
|
// 07/12/2000
|
|
// NTRaid : 142348
|
|
// Query for the rowset only if any rowset is asked for
|
|
if ( !(dwFlags & EXECUTE_NOROWSET) )
|
|
{
|
|
|
|
//=========================================================================
|
|
// Get the requested interface
|
|
//=========================================================================
|
|
if ( FAILED(hr = pCRowset->QueryInterface( riid, (LPVOID*) ppRowsets)) ){
|
|
// g_pCError->PostHResult(hr, pIID);
|
|
}
|
|
else{
|
|
//=====================================================================
|
|
// If IID_NULL was specified, it is assumed that you
|
|
// are not getting a rowset set back, but just in case
|
|
// we'll close the statement handle
|
|
//=====================================================================
|
|
|
|
}
|
|
}
|
|
} // If(!Failed(hr))
|
|
|
|
} // if succeeded(hr) after BuildBindInfo()
|
|
}
|
|
if (pCRowset)
|
|
{
|
|
pCRowset->Release();
|
|
}
|
|
if (pCUtlParam)
|
|
{
|
|
pCUtlParam->Release();
|
|
}
|
|
|
|
hr = FAILED(hr) ? hr : hrProp;
|
|
|
|
hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,pIID);
|
|
return hr;
|
|
|
|
/*
|
|
EXIT_EXECUTE:
|
|
//=========================================================================
|
|
// It is possible that we have gotten to this point and have handled off
|
|
// our pRowsetProps pointer to the rowset, but have no NULL'd the
|
|
// pointer. NULL it if flag is on.
|
|
//=========================================================================
|
|
if (dwFlags & EXECUTE_NULL_PROWSETPROPS)
|
|
pRowsetProps = NULL;
|
|
|
|
if (pCRowset)
|
|
pCRowset->Release();
|
|
|
|
if (pCUtlParam){
|
|
pCUtlParam->Release();
|
|
}
|
|
|
|
delete pRowsetProps;
|
|
|
|
return hr;*/
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Function to get the DBPROP_WMIOLEDB_QUERYLANGUAGE property
|
|
// NTRaid 134165
|
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CCommand::GetQueryLanguage(VARIANT &varProp)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
ULONG cPropertySets = 0;
|
|
DBPROPSET* prgPropertySets = NULL;
|
|
DBPROPIDSET rgPropertyIDSets[1];
|
|
DBPROPID rgPropId[1];
|
|
|
|
|
|
VariantClear(&varProp);
|
|
|
|
//========================================================================
|
|
// Get the value of the required rowset property
|
|
//========================================================================
|
|
rgPropertyIDSets[0].guidPropertySet = DBPROPSET_WMIOLEDB_ROWSET;
|
|
rgPropertyIDSets[0].rgPropertyIDs = rgPropId;
|
|
rgPropertyIDSets[0].cPropertyIDs = 1;
|
|
rgPropId[0] = DBPROP_WMIOLEDB_QUERYLANGUAGE;
|
|
|
|
if( S_OK == (hr = m_pUtilProps->GetProperties( PROPSET_COMMAND, 1, rgPropertyIDSets,&cPropertySets, &prgPropertySets )))
|
|
VariantCopy(&varProp,&prgPropertySets->rgProperties->vValue);
|
|
|
|
//==========================================================================
|
|
// Free memory we allocated to by GetProperties
|
|
//==========================================================================
|
|
m_pUtilProps->m_PropMemMgr.FreeDBPROPSET( cPropertySets, prgPropertySets);
|
|
|
|
return hr;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//***********************************************************************************************************
|
|
//
|
|
// Class CQuery
|
|
//
|
|
//***********************************************************************************************************
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
CQuery::CQuery()
|
|
{
|
|
m_prgbCallParams = NULL;
|
|
m_dwStatus = 0;
|
|
m_dwCancelStatus = 0;
|
|
m_prgProviderParamInfo = NULL;
|
|
m_pwstrWMIText = NULL;
|
|
m_pwstrQryLang = NULL;
|
|
|
|
//===============================================
|
|
// Init critical section
|
|
//===============================================
|
|
m_pcsQuery = new CCriticalSection(TRUE);
|
|
m_uRsType = COMMAND_ROWSET; // By default, set it for commands, can reset it to methods when needed.
|
|
m_pParamList = NULL;
|
|
|
|
}
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
CQuery::~CQuery()
|
|
{
|
|
DeleteConsumerParamInfo();
|
|
SAFE_DELETE_ARRAY( m_prgProviderParamInfo );
|
|
SAFE_DELETE_ARRAY( m_prgbCallParams );
|
|
SAFE_DELETE_PTR( m_pcsQuery );
|
|
SAFE_DELETE_ARRAY( m_pwstrWMIText );
|
|
SAFE_DELETE_ARRAY( m_pwstrQryLang );
|
|
|
|
}
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Deletes the consumer specified parameter information.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
void CQuery::DeleteConsumerParamInfo(void)
|
|
{
|
|
ULONG iElem;
|
|
|
|
if( m_pParamList ){
|
|
ULONG cElem = GetParamCount();
|
|
for (iElem = 0; iElem < cElem; iElem++) {
|
|
PPARAMINFO pParamInfo;
|
|
pParamInfo = (PPARAMINFO) m_pParamList->GetAt(iElem);
|
|
delete pParamInfo;
|
|
}
|
|
SAFE_DELETE_PTR(m_pParamList);
|
|
}
|
|
}
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Deletes the consumer specified parameter information.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CQuery::AddConsumerParamInfo(ULONG_PTR ulParams,PPARAMINFO pParamInfo)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
if( !m_pParamList ){
|
|
m_pParamList = new CFlexArray(PARAM_LIST_SIZE,50);
|
|
}
|
|
|
|
|
|
if( m_pParamList ){
|
|
|
|
if( ulParams < PARAM_LIST_SIZE ){
|
|
|
|
m_pParamList->InsertAt((int)ulParams,pParamInfo);
|
|
hr = S_OK;
|
|
}
|
|
else{
|
|
|
|
// There is a bug here with CFlexArray, when you add to it, it messes up the ordinal position
|
|
// need to work with the owners of CFlexArray to fix this
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Gets the parameter information for a specific parameter.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
PPARAMINFO CQuery::GetParamInfo( ULONG iParams )
|
|
{
|
|
PPARAMINFO pParamInfo = NULL;
|
|
ULONG uSize = GetParamCount();
|
|
if( uSize > 0 ){
|
|
if ( iParams <= uSize){
|
|
|
|
pParamInfo = (PPARAMINFO)m_pParamList->GetAt(iParams);
|
|
if (pParamInfo)
|
|
return pParamInfo;
|
|
}
|
|
pParamInfo = m_prgProviderParamInfo ? m_prgProviderParamInfo + iParams : NULL;
|
|
}
|
|
return pParamInfo;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CQuery::InitQuery(BSTR strQryLang)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if( m_pwstrWMIText ){
|
|
delete []m_pwstrWMIText;
|
|
}
|
|
m_pwstrWMIText = NULL;
|
|
|
|
// NTRaid 135165
|
|
hr = SetQueryLanguage(strQryLang);
|
|
|
|
return hr;
|
|
}
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CQuery::GetQuery(WCHAR *& wcsQuery)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
//===============================================================================
|
|
// Initialize output parameter
|
|
//===============================================================================
|
|
wcsQuery = NULL;
|
|
//===============================================================================
|
|
// Allocate memory for the string we're going to return to the caller
|
|
//===============================================================================
|
|
wcsQuery = (LPWSTR)g_pIMalloc->Alloc((wcslen(m_pwstrWMIText) + 1) * sizeof(WCHAR));
|
|
if ( !wcsQuery ){
|
|
hr = g_pCError->PostHResult((E_OUTOFMEMORY), &IID_ICommandText);
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
else{
|
|
wcscpy(wcsQuery, m_pwstrWMIText);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CQuery::SetQuery(LPCOLESTR wcsQuery, GUID rguidDialect)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
ULONG cwch = wcslen(wcsQuery);
|
|
LPWSTR pwstr = new WCHAR[cwch+2];
|
|
if (pwstr){
|
|
|
|
//=================================================================
|
|
// Save the text and dialect
|
|
//=================================================================
|
|
m_cwchWMIText = cwch;
|
|
m_pwstrWMIText = pwstr;
|
|
wcscpy(pwstr, wcsQuery);
|
|
m_guidCmdDialect = rguidDialect;
|
|
|
|
//=================================================================
|
|
// Set status flag that we have set text
|
|
//=================================================================
|
|
m_dwStatus = CMD_TEXT_SET;
|
|
|
|
//=================================================================
|
|
// Count the number of parameters
|
|
//pcmd->m_cParams = pcmd->CountParamMarkers(pwstr, cwch);
|
|
//=================================================================
|
|
hr = S_OK;
|
|
}
|
|
else{
|
|
hr = g_pCError->PostHResult((E_OUTOFMEMORY),&IID_ICommandText);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CQuery::SetDefaultQuery()
|
|
{
|
|
m_cwchWMIText = 0;
|
|
InitQuery();
|
|
m_guidCmdDialect = DBGUID_WQL;
|
|
m_dwStatus &= ~CMD_TEXT_SET;
|
|
|
|
return S_OK;
|
|
}
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CQuery::CancelQuery()
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
DBTYPE CQuery::GetParamType(DBORDINAL lOrdinal)
|
|
{
|
|
PPARAMINFO param = NULL;
|
|
|
|
param = (PPARAMINFO)m_pParamList->GetAt((int)lOrdinal);
|
|
assert(param);
|
|
|
|
return param->wOLEDBType;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// set the query language
|
|
// NTRaid 135165
|
|
////////////////////////////////////////////////////////////////////////
|
|
HRESULT CQuery::SetQueryLanguage(BSTR strQryLang)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
if(strQryLang)
|
|
{
|
|
SAFE_DELETE_ARRAY( m_pwstrQryLang );
|
|
m_pwstrQryLang = new WCHAR[(SysStringLen(strQryLang) + 1) * sizeof(WCHAR)];
|
|
if(m_pwstrQryLang)
|
|
{
|
|
wcscpy(m_pwstrQryLang,strQryLang);
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
else
|
|
if(m_pwstrQryLang == NULL)
|
|
{
|
|
m_pwstrQryLang = new WCHAR[wcslen(DEFAULTQUERYLANG) + 1];
|
|
if(m_pwstrQryLang)
|
|
{
|
|
wcscpy(m_pwstrQryLang,DEFAULTQUERYLANG);
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
} |