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

758 lines
22 KiB
C++

///////////////////////////////////////////////////////////////////////////////////
//
// Microsoft WMIOLE DB Provider
// (C) Copyright 1999 Microsoft Corporation. All Rights Reserved.
//
// CBinder object implementation
//
//
///////////////////////////////////////////////////////////////////////////////////
#include "headers.h"
#include "WmiOleDBMap.h"
///////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////
CBinder::CBinder(LPUNKNOWN pUnkOuter) : CBaseObj(BOT_BINDER,pUnkOuter)
{
m_cRef = 0;
m_pICreateRow = NULL;
m_pIBinderProperties = NULL;
m_pIBindResource = NULL;
m_pISupportErrorInfo = NULL;
m_pDataSrc = NULL;
m_pSession = NULL;
m_pUrlParser = NULL;
m_fDSOInitialized = FALSE;
//===============================================================
// Increment global object count.
//===============================================================
InterlockedIncrement(&g_cObj);
}
///////////////////////////////////////////////////////////////////////////////////
// Destructor
///////////////////////////////////////////////////////////////////////////////////
CBinder::~CBinder()
{
HRESULT hr = S_OK;
IDBInitialize *pInitialize = NULL;
SAFE_RELEASE_PTR(m_pSession);
SAFE_RELEASE_PTR(m_pDataSrc);
SAFE_DELETE_PTR(m_pICreateRow);
SAFE_DELETE_PTR(m_pIBinderProperties);
SAFE_DELETE_PTR(m_pIBindResource);
SAFE_DELETE_PTR(m_pISupportErrorInfo);
SAFE_DELETE_PTR(m_pUrlParser);
SAFE_DELETE_PTR(m_pUtilProp);
//===============================================================
// Decrement global object count.
//===============================================================
InterlockedDecrement(&g_cObj);
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// Function to navigate between the different interfaces
/////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CBinder::QueryInterface ( REFIID riid, LPVOID * ppv)
{
HRESULT hr = S_OK;
//======================================================
// Check parameters, if not valid return
//======================================================
if (NULL == ppv){
hr = E_INVALIDARG ;
}
else
{
//======================================================
// Place NULL in *ppv in case of failure
//======================================================
*ppv = NULL;
//======================================================
// This is the non-delegating IUnknown implementation
//======================================================
if (riid == IID_IUnknown)
{
*ppv = (LPVOID) this;
}
else if (riid == IID_IBindResource)
{
*ppv = (LPVOID) m_pIBindResource;
}
else if (riid == IID_IDBBinderProperties || riid == IID_IDBProperties)
{
*ppv = (LPVOID) m_pIBinderProperties;
}
else if (riid == IID_ICreateRow)
{
*ppv = (LPVOID) m_pICreateRow;
}
else if(riid == IID_ISupportErrorInfo)
{
*ppv = (LPVOID)m_pISupportErrorInfo;
}
//======================================================
// If we're going to return an interface, AddRef first
//======================================================
if (*ppv){
((LPUNKNOWN) *ppv)->AddRef();
hr = S_OK ;
}
else{
hr = E_NOINTERFACE;
}
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// Increments a persistence count for the object
//
// Current reference count
//
/////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_( ULONG ) CBinder::AddRef( void )
{
return InterlockedIncrement((long*)&m_cRef);
}
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// Decrements a persistence count for the object and if persistence count is 0, the object
// destroys itself.
//
/////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_( ULONG ) CBinder::Release( void )
{
InterlockedDecrement((long*)&m_cRef);
if (!m_cRef){
g_pIDataConvert->Release();
delete this;
return 0;
}
return m_cRef;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// Function to initialize the binder object
/////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CBinder::InitBinder()
{
HRESULT hr = S_OK;
BOOL bRet = TRUE;
//================================================
// Instantiate the data conversion service object
//================================================
if( !g_pIDataConvert ){
hr = CoCreateInstance(CLSID_OLEDB_CONVERSIONLIBRARY, NULL, CLSCTX_INPROC_SERVER, IID_IDataConvert, (void **)&g_pIDataConvert);
}
else
{
//============================================
// Already instantiated, increment reference
// count
//============================================
g_pIDataConvert->AddRef();
}
if(SUCCEEDED(hr))
{
IDCInfo *pDcInfo = NULL;
DCINFO dcInfo[1];
dcInfo[0].eInfoType = DCINFOTYPE_VERSION;
V_VT(&dcInfo[0].vData) = VT_UI4;
V_UI4(&dcInfo[0].vData) = 0x200;
hr = g_pIDataConvert->QueryInterface(IID_IDCInfo,(void **)&pDcInfo);
hr = pDcInfo->SetInfo(1,dcInfo);
//================================================
// Allocate properties management object
//================================================
m_pUtilProp = new CUtilProp;
if(m_pUtilProp == NULL)
{
hr = E_OUTOFMEMORY;
}
else
// NTRaid: 136443
// 07/05/00
if(SUCCEEDED(hr = m_pUtilProp->FInit(BINDERPROP)))
{
//================================================
// Allocate the URLParser class
//================================================
m_pUrlParser = new CURLParser;
//================================================
// Allocate contained interface objects
//================================================
m_pIBindResource = new CImplIBindResource( this );
m_pICreateRow = new CImplICreateRow( this );
m_pIBinderProperties = new CImplIDBBinderProperties( this );
m_pISupportErrorInfo = new CImpISupportErrorInfo(this);
if(!((BOOL)(m_pUtilProp && m_pUrlParser && m_pIBindResource && m_pICreateRow && m_pIBinderProperties && m_pISupportErrorInfo)))
{
hr = E_OUTOFMEMORY;
}
}
}
if(SUCCEEDED(hr))
{
hr = AddInterfacesForISupportErrorInfo();
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
// Function to add interfaces to ISupportErrorInfo interface
/////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CBinder::AddInterfacesForISupportErrorInfo()
{
HRESULT hr = S_OK;
if(SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_IBindResource)))
if(SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_IDBBinderProperties)))
if(SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_IDBProperties)))
{
hr = m_pISupportErrorInfo->AddInterfaceID(IID_ICreateRow);
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// Function to Create a Datasource object. The init flat parameter is the flags obtained
// from the binder flags passed to the IBinderResource::Bind function
// If the caller needs a pointer to a particular interface , then the id of the interface
// required will be passed in riid parmeter , otherwise this parameter will be GUID_NULL
/////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CBinder::CreateDSO(IUnknown *pUnkOuter,LONG lInitFlag, REFGUID riid,IUnknown ** ppUnk)
{
HRESULT hr = E_FAIL;
IDBInitialize * pInitialize = NULL;
IDBProperties * pDBProperties = NULL;
DBPROPSET rgPropertySets[1];
DBPROPIDSET rgPropIDSet[1];
DBPROP rgprop[1];
VARIANT varValue;
ULONG cPropSets = 1;
DBPROPSET* prgPropertySets;
DBPROPID rgPropId[1];
if(m_pDataSrc != NULL)
{
hr = S_OK;
if( riid != GUID_NULL)
{
//=============================================
// Get the required interface pointer
//=============================================
hr = m_pDataSrc->QueryInterface(riid , (void **)ppUnk);
}
}
else
{
memset(&rgprop[0],0,sizeof(DBPROP));
memset(&rgPropertySets[0],0,sizeof(DBPROPSET));
VariantInit(&varValue);
CDataSource *pDatasource = NULL;
try
{
//=============================================
// Allocate a new datasource object
//=============================================
pDatasource = new CDataSource( pUnkOuter );
}
catch(...)
{
SAFE_DELETE_PTR(pDatasource);
throw;
}
if(pDatasource == NULL)
{
hr = E_OUTOFMEMORY;
}
else
if(SUCCEEDED(hr = pDatasource->FInit()))
{
//==================================================================
// QI for IUnknown and save pointer in the member variable
//==================================================================
if(SUCCEEDED(hr =pDatasource->QueryInterface(IID_IUnknown , (void **)&m_pDataSrc)))
if(SUCCEEDED(hr = m_pDataSrc->QueryInterface(IID_IDBProperties ,(void **)&pDBProperties)))
{
rgPropIDSet[0].cPropertyIDs = 0;
rgPropIDSet[0].guidPropertySet = DBPROPSET_DBINIT;
//==================================================================
// Get the properties set thru IDBBinderProperties
//==================================================================
hr = m_pUtilProp->GetProperties(PROPSET_INIT,0,rgPropIDSet, &cPropSets,&prgPropertySets);
if(SUCCEEDED(hr = pDBProperties->SetProperties(cPropSets,prgPropertySets)))
{
//==========================================================================
// Free memory we allocated to by GetProperties
//==========================================================================
m_pUtilProp->m_PropMemMgr.FreeDBPROPSET( cPropSets, prgPropertySets);
rgPropId[0] = DBPROP_INIT_DATASOURCE;
rgPropIDSet[0].guidPropertySet = DBPROPSET_DBINIT;
rgPropIDSet[0].rgPropertyIDs = rgPropId;
rgPropIDSet[0].cPropertyIDs = 1;
hr = m_pUtilProp->GetProperties( PROPSET_INIT,1, rgPropIDSet,&cPropSets,&prgPropertySets );
if(SUCCEEDED(hr))
{
// if the property set is not empty then get the property DBPROP_INIT_DATASOURCE
// else extract it from URL
if(prgPropertySets[0].rgProperties[0].vValue.vt == VT_BSTR &&
prgPropertySets[0].rgProperties[0].vValue.bstrVal != NULL &&
SysStringLen(prgPropertySets[0].rgProperties[0].vValue.bstrVal) > 0)
{
rgprop[0].vValue.bstrVal = Wmioledb_SysAllocString(prgPropertySets[0].rgProperties[0].vValue.bstrVal);
}
else
{
m_pUrlParser->GetNameSpace(rgprop[0].vValue.bstrVal);
}
//==========================================================================
// Free memory we allocated to by GetProperties
//==========================================================================
m_pUtilProp->m_PropMemMgr.FreeDBPROPSET( cPropSets, prgPropertySets);
//==================================================================
// Get the namespace from the Parser and then set
// the DBPROP_INIT_DATASOURCE property
//==================================================================
rgprop[0].dwPropertyID = DBPROP_INIT_DATASOURCE;
rgprop[0].vValue.vt = VT_BSTR;
// m_pUrlParser->GetNameSpace(rgprop[0].vValue.bstrVal);
rgPropertySets[0].rgProperties = &rgprop[0];
rgPropertySets[0].cProperties = 1;
rgPropertySets[0].guidPropertySet = DBPROPSET_DBINIT;
if(SUCCEEDED(hr = pDBProperties->SetProperties(1,rgPropertySets)))
{
// set the properties on the current property handler
hr = m_pUtilProp->SetProperties(PROPSET_INIT,1,rgPropertySets);
}
SAFE_FREE_SYSSTRING(rgprop[0].vValue.bstrVal);
}
if(SUCCEEDED(hr))
{
VariantClear(&(rgprop[0].vValue));
//========================================
// Setting the DBPROP_DBINIT property
//========================================
rgprop[0].dwPropertyID = DBPROP_INIT_MODE;
rgprop[0].vValue.vt =VT_I4;
rgprop[0].vValue.lVal = lInitFlag;
rgPropertySets[0].rgProperties = &rgprop[0];
rgPropertySets[0].cProperties = 1;
rgPropertySets[0].guidPropertySet = DBPROPSET_DBINIT;
if(SUCCEEDED(hr = pDBProperties->SetProperties(1,rgPropertySets)) &&
SUCCEEDED(hr = m_pUtilProp->SetProperties(PROPSET_INIT,1,rgPropertySets)))
{
//===============================================
// Get the pointer to IDBInitialize interface
//===============================================
hr = m_pDataSrc->QueryInterface(IID_IDBInitialize, (void **)&pInitialize);
//===============================================================
// Initialize the Datasource object if
// the flag does not indicate waiting for the initialization
//===============================================================
if(!(lInitFlag & DBBINDURLFLAG_WAITFORINIT))
{
if(S_OK == (hr = pInitialize->Initialize()))
m_fDSOInitialized = TRUE;
}
if(S_OK == hr)
{
if( riid != GUID_NULL)
{
//========================================
// Get the required interface pointer
//========================================
hr = m_pDataSrc->QueryInterface(riid , (void **)ppUnk);
}
}
pInitialize->Release();
pDBProperties->Release();
} // If(Succeeded(call to SetProperties)) of DBPROP_INIT_MODE property
} // If(Succeeded(call to SetProperties)) of DBPROP_INIT_DATASOURCE property
} // If(Succeeded(call to SetProperties))
} // If Succeeded() for QI
} // if(Succeeded(pDatasource->FInit()))
else
{
hr = E_FAIL;
}
} // Else for if(m_pDataSrc != NULL)
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// Function to create a session object
/////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CBinder::CreateSession(IUnknown *pUnkOuter, REFGUID riid,IUnknown ** ppUnk)
{
HRESULT hr = S_OK;
IDBCreateSession * pDBCreateSession = NULL;
IDBInitialize * pInitialize = NULL;
assert(m_pDataSrc != NULL);
//====================================================================
// If the datasource is not yet initialized , then initialize it
//====================================================================
if(m_fDSOInitialized == FALSE)
{
//================================================
// Get the pointer to IDBInitialize interface
//================================================
hr = m_pDataSrc->QueryInterface(IID_IDBInitialize, (void **)&pInitialize);
if(S_OK == (hr = pInitialize->Initialize()))
{
m_fDSOInitialized = TRUE;
}
pInitialize->Release();
}
if(SUCCEEDED(hr))
if(S_OK ==(hr = m_pDataSrc->QueryInterface(IID_IDBCreateSession,(void **)&pDBCreateSession)))
{
//======================
// Create session
//======================
if(S_OK ==(hr = pDBCreateSession->CreateSession(pUnkOuter,IID_IUnknown,(IUnknown**)&m_pSession)))
{
if(riid != GUID_NULL)
{
hr = m_pSession->QueryInterface(riid,(void **)ppUnk);
}
}
}
if(pDBCreateSession)
{
pDBCreateSession->Release();
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// Function to create a Command object
/////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CBinder::CreateCommand(IUnknown *pUnkOuter, REFGUID guidTemp,IUnknown ** ppUnk)
{
return m_pSession->CreateCommand(pUnkOuter, guidTemp,ppUnk);
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// Function to create a required row object
// NTRaid:136539 , 136540
// 07/05/00
/////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CBinder::CreateRow(IUnknown *pUnkOuter, REFGUID riid,IUnknown ** ppUnk ,ROWCREATEBINDFLAG rowCreateFlag)
{
HRESULT hr = E_FAIL;
IUnknown * pUnkRow = NULL;
BSTR strTable = NULL;
BSTR strPath = NULL;
CDBSession * pDBSess = NULL;
ISessionProperties *pSessProp = NULL;
CRow * pNewRow = NULL;
DBPROPSET * pPropSet = NULL;
if( S_OK == (hr = m_pSession->QueryInterface(IID_ISessionProperties , (void **)&pSessProp)))
{
pDBSess = ((CImpISessionProperties *)pSessProp)->GetSessionPtr();
pSessProp->Release();
// Get the path of the object
hr = m_pUrlParser->GetPathWithEmbededInstInfo(strPath);
// Get the class name
// m_pUrlParser->GetClassName(strTable);
// NTRaid : 134967
// 07/12/00
if(SUCCEEDED(hr) && SUCCEEDED(hr = m_pUtilProp->GetConnectionInitProperties(&pPropSet)))
{
hr = GetClassName(m_pUrlParser,pPropSet,strTable,m_pDataSrc->m_pWbemWrap);
}
//==========================================================================
// Free memory we allocated to get the namespace property above
//==========================================================================
CPropertyMemoryMgr::FreeDBPROPSET( 1, pPropSet);
if(SUCCEEDED(hr))
{
try
{
// currently hardcoded to NO_QUALIFIERS
pNewRow = new CRow(pUnkOuter,pDBSess);
}
catch(...)
{
SAFE_DELETE_PTR(pNewRow);
throw;
}
if( pNewRow == NULL)
{
hr = E_OUTOFMEMORY;
}
else
{
if(S_OK ==(hr = pNewRow->InitRow(strPath,strTable,-1,rowCreateFlag)))
{
hr = pNewRow->QueryInterface(riid,(void **)ppUnk);
}
if(hr == S_OK && rowCreateFlag != ROWOPEN)
{
hr = pNewRow->UpdateKeysForNewInstance();
}
}
//========================================================
// Free the strings allocated by the URLParser class
//========================================================
SysFreeString(strTable);
SysFreeString(strPath);
}
if(FAILED(hr))
{
SAFE_DELETE_PTR(pNewRow);
*ppUnk = NULL;
}
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// Function to create a Rowset object
/////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CBinder::CreateRowset(IUnknown *pUnkOuter, REFGUID riid,IUnknown ** ppUnk)
{
HRESULT hr = E_FAIL;
IOpenRowset * pOpenRowset = NULL;
DBPROPSET * pPropSet = NULL;
ULONG cPropSets = 1;
DBPROPSET* prgPropertySets = NULL;
BSTR strTableName = NULL;
assert(m_pSession != NULL);
//=========================================
// Get pointer to IOpenRowset interface
//=========================================
if(S_OK == (hr = m_pSession->QueryInterface(IID_IOpenRowset , (void **)&pOpenRowset)))
{
DBPROPIDSET rgPropIDSet[1];
rgPropIDSet[0].cPropertyIDs = 0;
rgPropIDSet[0].guidPropertySet = DBPROPSET_ROWSET;
//=========================================
// Get the properties
//=========================================
hr = m_pUtilProp->GetProperties(PROPSET_ROWSET,0,rgPropIDSet, &cPropSets,&prgPropertySets);
//=========================================
// Get the class name and initialize the tableID
//=========================================
// NTRaid : 134967
// 07/12/00
if(SUCCEEDED(hr))
{
if (SUCCEEDED(hr = m_pUtilProp->GetConnectionInitProperties(&pPropSet)))
{
hr = GetClassName(m_pUrlParser,pPropSet,strTableName,m_pDataSrc->m_pWbemWrap);
if (SUCCEEDED(hr))
{
DBID tableID;
memset(&tableID , 0 , sizeof(DBID));
tableID.eKind = DBKIND_NAME;
tableID.uName.pwszName = strTableName;
//=========================================
// Open the rowset
//=========================================
hr = pOpenRowset->OpenRowset(pUnkOuter,&tableID,NULL,riid,cPropSets,prgPropertySets,ppUnk);
SAFE_FREE_SYSSTRING(strTableName);
}
//==========================================================================
// Free memory we allocated to get the namespace property above
//==========================================================================
CPropertyMemoryMgr::FreeDBPROPSET( 1, pPropSet);
}
//==========================================================================
// Free memory we allocated to by GetProperties
//==========================================================================
m_pUtilProp->m_PropMemMgr.FreeDBPROPSET( cPropSets, prgPropertySets);
}
}
SAFE_RELEASE_PTR(pOpenRowset);
return hr;
}
/*
///////////////////////////////////////////////////////////////////////////////////////////////////
// Get Binding flags and put it in a variable as INIT_MODE flags
///////////////////////////////////////////////////////////////////////////////////////////////////
void CBinder::GetInitAndBindFlagsFromBindFlags(DBBINDURLFLAG dwBindURLFlags,LONG & lInitMode ,LONG & lInitBindFlags)
{
lInitMode = 0;
lInitBindFlags = 0;
// DBPROP_INIT_MODE
if(DBBINDURLFLAG_READ & dwBindURLFlags)
{
lInitMode = lInitMode | DB_MODE_READ;
}
if(DBBINDURLFLAG_WRITE & dwBindURLFlags)
{
lInitMode = lInitMode | DB_MODE_WRITE;
}
if(DBBINDURLFLAG_SHARE_DENY_READ & dwBindURLFlags)
{
lInitMode = lInitMode | DB_MODE_SHARE_DENY_READ;
}
if(DBBINDURLFLAG_SHARE_DENY_WRITE & dwBindURLFlags)
{
lInitMode = lInitMode | DB_MODE_SHARE_DENY_WRITE;
}
if(DBBINDURLFLAG_SHARE_EXCLUSIVE & dwBindURLFlags)
{
lInitMode = lInitMode | DB_MODE_SHARE_EXCLUSIVE;
}
if(DBBINDURLFLAG_SHARE_DENY_NONE & dwBindURLFlags)
{
lInitMode = lInitMode | DB_MODE_SHARE_DENY_NONE;
}
// DBPROP_INIT_BINDFLAGS
if(DBBINDURLFLAG_RECURSIVE & dwBindURLFlags)
{
lInitBindFlags = lInitBindFlags | DB_BINDFLAGS_RECURSIVE;
}
if(DBBINDURLFLAG_OUTPUT & dwBindURLFlags)
{
lInitBindFlags = lInitBindFlags | DB_BINDFLAGS_OUTPUT;
}
if(DBBINDURLFLAG_DELAYFETCHCOLUMNS & dwBindURLFlags)
{
lInitBindFlags = lInitBindFlags | DB_BINDFLAGS_DELAYFETCHCOLUMNS;
}
if(DBBINDURLFLAG_DELAYFETCHSTREAM & dwBindURLFlags)
{
lInitBindFlags = lInitBindFlags | DB_BINDFLAGS_DELAYFETCHSTREAM;
}
}
*/
////////////////////////////////////////////////////////////
// Function to release all the bound objects
////////////////////////////////////////////////////////////
HRESULT CBinder::ReleaseAllObjects()
{
SAFE_RELEASE_PTR(m_pDataSrc);
SAFE_RELEASE_PTR(m_pSession);
return S_OK;
}