//////////////////////////////////////////////////////////////////////////////////////////////////////// // // Microsoft WMI OLE DB Provider // (C) Copyright 1999 Microsoft Corporation. All Rights Reserved. // // Enumeration Routines // /////////////////////////////////////////////////////////////////////////////////////////////////////// #include "headers.h" #include "command.h" #include "schema.h" #include "enumerat.h" #define NAMESPACE_SEPARATOR L"\\" ////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Microsoft WMI OLE DB Provider // (C) Copyright 1999 Microsoft Corporation. All Rights Reserved. // // The module contains the DLL Entry and Exit points, plus the OLE ClassFactory class for RootBinder object. // ////////////////////////////////////////////////////////////////////////////////////////////////////////////// //#define DECLARE_GLOBALS //=============================================================================== // Don't include everything from windows.h, but always bring in OLE 2 support //=============================================================================== //#define WIN32_LEAN_AND_MEAN #define INC_OLE2 //=============================================================================== // Make sure constants get initialized //=============================================================================== #define INITGUID #define DBINITCONSTANTS //=============================================================================== // Basic Windows and OLE everything //=============================================================================== #include //=============================================================================== // OLE DB headers //=============================================================================== #include "oledb.h" #include "oledberr.h" //=============================================================================== // Data conversion library header //=============================================================================== #include "msdadc.h" //=============================================================================== // Guids for data conversion library //=============================================================================== #include "msdaguid.h" //=============================================================================== // GUIDs //=============================================================================== #include "guids.h" //=============================================================================== // Common project stuff //=============================================================================== #include "headers.h" #include "binderclassfac.h" //=============================================================================== // Globals //=============================================================================== extern LONG g_cObj; // # of outstanding objects extern LONG g_cLock; // # of explicit locks set extern DWORD g_cAttachedProcesses; // # of attached processes extern DWORD g_dwPageSize; // System page size /////////////////////////////////////////////////////////////////////////////////////////////////////// static const GUID* x_rgEnumeratorErrInt[] = { &IID_IParseDisplayName, &IID_ISourcesRowset, }; static const ULONG x_cEnumeratorErrInt = NUMELEM(x_rgEnumeratorErrInt); /////////////////////////////////////////////////////////////////////////////////////////////////////// #pragma warning (disable:4355) CEnumeratorNameSpace :: CEnumeratorNameSpace(LPUNKNOWN pUnkOuter): CBaseObj(BOT_ENUMERATOR,pUnkOuter), m_ISourcesRowset(this), m_IParseDisplayName(this) { m_dwStatus = 0; m_pCDataSource = NULL; m_pCDBSession = NULL; m_pISupportErrorInfo = NULL; } /////////////////////////////////////////////////////////////////////////////////////////////////////// #pragma warning (default:4355) CEnumeratorNameSpace :: ~CEnumeratorNameSpace (void) { //============================== // Release the session //============================== SAFE_RELEASE_PTR(m_pCDBSession); //============================== // Release the data source //============================== SAFE_RELEASE_PTR(m_pCDataSource); } /////////////////////////////////////////////////////////////////////////////////////////////////////// HRESULT CEnumeratorNameSpace::CreateDataSource() { HRESULT hr = E_FAIL; IDBInitialize * pInitialize = NULL; IDBProperties * pDBProperties = NULL; DBPROPSET rgPropertySets[1]; DBPROPIDSET rgPropIDSet[1]; DBPROP rgprop[1]; VARIANT varValue; ULONG cPropSets = 1; CDataSource *pDataSource = NULL; memset(&rgprop[0],0,sizeof(DBPROP)); memset(&rgPropertySets[0],0,sizeof(DBPROPSET)); VariantInit(&varValue); try { //======================================================== // Allocate a new datasource object //======================================================== pDataSource = new CDataSource( NULL ); } catch(...) { SAFE_RELEASE_PTR(pDataSource); throw; } if( !pDataSource ){ hr = E_OUTOFMEMORY; } else { hr = pDataSource->QueryInterface(IID_IUnknown,(void **)&m_pCDataSource); //======================================================== // Initialize the data source //======================================================== if(SUCCEEDED(hr = ((CDataSource*)m_pCDataSource)->FInit())){ if(!(FAILED(hr = m_pCDataSource->QueryInterface(IID_IDBProperties ,(void **)&pDBProperties)))) { rgPropIDSet[0].cPropertyIDs = 0; rgPropIDSet[0].guidPropertySet = DBPROPSET_DBINIT; //================================================================================ // Get the properties set before.... //================================================================================ // hr = m_pUtilProp->GetProperties(0,0,rgPropIDSet, &cPropSets,&prgPropertySets); // hr = pDBProperties->SetProperties(cPropSets,prgPropertySets); // if(FAILED(hr)){ // return hr; // } //================================================================================ // Always use the root namespace, & set the DBPROP_INIT_DATASOURCE property //================================================================================ CVARIANT v(ROOT_NAMESPACE); rgprop[0].dwPropertyID = DBPROP_INIT_DATASOURCE; rgprop[0].vValue.vt = VT_BSTR; rgprop[0].vValue.bstrVal = v; rgPropertySets[0].rgProperties = &rgprop[0]; rgPropertySets[0].cProperties = 1; rgPropertySets[0].guidPropertySet = DBPROPSET_DBINIT; if(SUCCEEDED(hr = pDBProperties->SetProperties(1,rgPropertySets))) { //================================================================================ // Get the pointer to IDBInitialize interface //================================================================================ if(SUCCEEDED(hr = m_pCDataSource->QueryInterface(IID_IDBInitialize, (void **)&pInitialize))) { //============================================================================ // Initialize the Datasource object //============================================================================ hr = pInitialize->Initialize(); } // SAFE_RELEASE_PTR(m_pCDataSource); } // succeeded of SetProperties } // succeeeded of QI } // if(((CDataSource*)m_pCDataSource)-FInit()>) } // Else for if( !m_pCDataSource ) return hr; } /////////////////////////////////////////////////////////////////////////////////////////////////////// // // Initializes enumerator object. Instantiate interface implementation objects. // /////////////////////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CEnumeratorNameSpace::Initialize(void) { const IID* piid = &IID_ISourcesRowset; HRESULT hr = S_OK; if (!(m_dwStatus & ENK_DIDINIT)){ //========================================================= // Allocate and initialize a DataSource object //========================================================= if( SUCCEEDED(hr == CreateDataSource()) ){ //===================================================== // Allocate and initialize a Session object //===================================================== IDBCreateSession *pDBCreateSession = NULL; m_pISupportErrorInfo = new CImpISupportErrorInfo(this); assert(m_pCDataSource != NULL); // NTRaid:136454 // 07/05/00 if(m_pISupportErrorInfo) { hr = m_pCDataSource->QueryInterface(IID_IDBCreateSession,(void **)&pDBCreateSession); if( S_OK == hr ){ //=============================================== // Create session //=============================================== hr = pDBCreateSession->CreateSession(m_pUnkOuter,IID_IUnknown,&m_pCDBSession); if( hr == S_OK ){ m_dwStatus |= ENK_DIDINIT; m_pCDBSession->AddRef(); } } if(pDBCreateSession){ pDBCreateSession->Release(); } } else { hr = E_OUTOFMEMORY; } } if(SUCCEEDED(hr)) { hr = AddInterfacesForISupportErrorInfo(); } } if(hr != S_OK ){ g_pCError->PostWMIErrors(hr, piid,GetDataSource()->GetErrorDataPtr()); SAFE_RELEASE_PTR(m_pCDataSource); SAFE_RELEASE_PTR(m_pCDBSession); } else{ g_pCError->PostHResult(hr, piid); } return hr; } ///////////////////////////////////////////////////////////////////////////////////////////////////// // Function to add interfaces to ISupportErrorInfo interface ///////////////////////////////////////////////////////////////////////////////////////////////////// HRESULT CEnumeratorNameSpace::AddInterfacesForISupportErrorInfo() { HRESULT hr = S_OK; if(SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_ISourcesRowset))) { hr = m_pISupportErrorInfo->AddInterfaceID(IID_IParseDisplayName); } return hr; } ///////////////////////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP_(ULONG) CEnumeratorNameSpace::AddRef(void) { return InterlockedIncrement( (long*) &m_cRef); } ///////////////////////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP_(ULONG) CEnumeratorNameSpace::Release(void) { ULONG cRef = InterlockedDecrement( (long*) &m_cRef); if ( !cRef ) delete this; return cRef; } ///////////////////////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CEnumeratorNameSpace::QueryInterface( REFIID riid, LPVOID *ppv ) { HRESULT hr = S_OK; //=========================================== // Is the pointer bad? //=========================================== if ( ppv == NULL ) { hr = E_INVALIDARG; } { //=========================================== // This is the non-delegating IUnknown // implementation //=========================================== if ( riid == IID_IUnknown ) *ppv = (LPVOID)this; else if ( riid == IID_ISourcesRowset ) *ppv = (LPVOID)&m_ISourcesRowset; else if ( riid == IID_IParseDisplayName ) *ppv = (LPVOID)&m_IParseDisplayName; else if ( riid == IID_ISupportErrorInfo ) *ppv = (LPVOID)m_pISupportErrorInfo; else //======================================= // Place NULL in *ppv in case of failure //======================================= *ppv = NULL; if ( *ppv ){ ((LPUNKNOWN)*ppv)->AddRef(); hr = S_OK; } else { hr = E_NOINTERFACE; } } return hr; } ///////////////////////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP_(ULONG) CImpISourcesRowset::AddRef(void) { InterlockedIncrement((long*)&m_cRef); return m_pCEnumeratorNameSpace->AddRef(); } ///////////////////////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP_(ULONG) CImpISourcesRowset::Release(void) { InterlockedDecrement((long*)&m_cRef); return m_pCEnumeratorNameSpace->Release(); } ///////////////////////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CImpISourcesRowset::QueryInterface( REFIID riid, LPVOID * ppv ) { return m_pCEnumeratorNameSpace->QueryInterface(riid, ppv); } ///////////////////////////////////////////////////////////////////////////////////////////////////////// // // Instantiate a rowset with a list of data sources. // ///////////////////////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CImpISourcesRowset::GetSourcesRowset( IUnknown* pUnkOuter, REFIID riid, ULONG cPropertySets,DBPROPSET rgPropertySets[], IUnknown** ppIRowset ) { HRESULT hr = E_INVALIDARG; CSchema_ISourcesRowset *pCSchema = NULL; CSetStructuredExceptionHandler seh; TRY_BLOCK; //===================================================================== // Check parameters //===================================================================== assert( m_pCEnumeratorNameSpace ); //===================================================================== // NULL out-params in case of error //===================================================================== //=============================================================== // Clear previous Error Object for this thread //=============================================================== g_pCError->ClearErrorInfo(); if(ppIRowset) { *ppIRowset = NULL; } //===================================================================== // Check Arguments //===================================================================== if ( riid == IID_NULL){ hr = E_NOINTERFACE ; } else if ( (pUnkOuter) && (riid != IID_IUnknown) ){ // We do not allow the riid to be anything other than IID_IUnknown for aggregation hr = DB_E_NOAGGREGATION ; } else { //=============================================================== // Serialize access to this object. //=============================================================== CAutoBlock block(m_pCEnumeratorNameSpace->GetCriticalSection()); //=============================================================== // Spec-defined error checks. //=============================================================== if (!ppIRowset || (cPropertySets && !rgPropertySets)){ hr = E_INVALIDARG ; } else{ //=========================================================== // The outer object must explicitly ask for IUnknown //=========================================================== if (pUnkOuter != NULL && riid != IID_IUnknown){ hr = DB_E_NOAGGREGATION; } else{ if (SUCCEEDED(hr = m_pCEnumeratorNameSpace->Initialize())){ try { pCSchema = new CSchema_ISourcesRowset(pUnkOuter,m_pCEnumeratorNameSpace->GetSession()); } catch(...) { SAFE_DELETE_PTR(pCSchema); throw; } if (!pCSchema){ hr = E_OUTOFMEMORY; } else{ hr = pCSchema->FInit(cPropertySets, rgPropertySets, riid, pUnkOuter, ppIRowset,NULL); } } } } if( FAILED(hr ) ){ SAFE_RELEASE_PTR( pCSchema ); *ppIRowset = NULL; } } // else hr = hr != S_OK ? g_pCError->PostHResult(hr,&IID_ISourcesRowset): hr; CATCH_BLOCK_HRESULT(hr,L"ISourcesRowset::GetSourcesRowset"); return hr; } ///////////////////////////////////////////////////////////////////////////////////////////////////////// // // CImpIParseDisplayName // ///////////////////////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP_(ULONG) CImpIParseDisplayName::AddRef(void) { InterlockedIncrement((long*)&m_cRef); return m_pCEnumeratorNameSpace->AddRef(); } ///////////////////////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP_(ULONG) CImpIParseDisplayName::Release(void) { InterlockedDecrement((long*)&m_cRef); return m_pCEnumeratorNameSpace->Release(); } ///////////////////////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CImpIParseDisplayName::QueryInterface( REFIID riid, LPVOID * ppv ) { return m_pCEnumeratorNameSpace->QueryInterface(riid, ppv); } ///////////////////////////////////////////////////////////////////////////////////////////////////////// // // Function creates moniker according to the name passed to it. // ///////////////////////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CImpIParseDisplayName::ParseDisplayName( IBindCtx *pbc, WCHAR *pwszDisplayName, ULONG *pchEaten, IMoniker **ppIMoniker) { //=========================================================== // // Instantiate Data Source Object. // Set all interesting properties. // Initialize object. // Create pointer moniker and pass it out. // // Need to find out a way to use IBindCtx. // //=========================================================== HRESULT hr = S_OK; CSetStructuredExceptionHandler seh; TRY_BLOCK; if (ppIMoniker) { *ppIMoniker = NULL; } if (!pwszDisplayName || !pchEaten){ hr = MK_E_NOOBJECT; // return g_pCError->PostHResult((MK_E_NOOBJECT), &IID_IParseDisplayName); } else if (!ppIMoniker){ hr = E_UNEXPECTED; // return g_pCError->PostHResult((E_UNEXPECTED),&IID_IParseDisplayName); } else { IClassFactory * pIClassFact=NULL; IDBProperties * pIDBProps=NULL; IUnknown * pIUnknown=NULL; //=========================================================== //Define Property Structures. //=========================================================== ULONG cPropertySets; DBPROPSET rgPropertySet[1]; DBPROP rgProperties[1]; //=========================================================== // Clear Error Messages on current thread //=========================================================== g_pCError->ClearErrorInfo(); //=========================================================== // Initialize property values //=========================================================== VariantInit(&rgProperties[0].vValue); hr = CoCreateInstance( CLSID_WMIOLEDB,NULL, CLSCTX_INPROC_SERVER, IID_IDBProperties, (void**)&pIDBProps); CURLParser urlParser; CBSTR strTemp,strKey; VARIANT varKeyVal; int lSizeToAlloc = 0; WCHAR *pstrNamespace = NULL; VariantInit(&varKeyVal); strTemp.SetStr(pwszDisplayName); urlParser.SetPath(strTemp); strTemp.Clear(); urlParser.GetNameSpace((BSTR &)strTemp); strKey.SetStr(L"Name"); // Get the Name of the NameSpace urlParser.GetKeyValue(strKey,varKeyVal); lSizeToAlloc = (SysStringLen(varKeyVal.bstrVal) + SysStringLen(strTemp) + wcslen(NAMESPACE_SEPARATOR) + 1 ) * sizeof(WCHAR); try { pstrNamespace = new WCHAR[lSizeToAlloc]; } catch(...) { SAFE_DELETE_ARRAY(pstrNamespace); throw; } if(!pstrNamespace) { hr = E_OUTOFMEMORY; } else { // Frame the Namespace string memset(pstrNamespace,0,lSizeToAlloc * sizeof(WCHAR)); memcpy(pstrNamespace,strTemp,SysStringLen(strTemp) * sizeof(WCHAR)); wcscat(pstrNamespace,NAMESPACE_SEPARATOR); memcpy((pstrNamespace + wcslen(pstrNamespace)),varKeyVal.bstrVal,SysStringLen(varKeyVal.bstrVal) * sizeof(WCHAR)); if (SUCCEEDED(hr)){ //======================================================= //Set Init properties. //======================================================= cPropertySets = 1; rgPropertySet[0].rgProperties = rgProperties; rgPropertySet[0].cProperties = 1; rgPropertySet[0].guidPropertySet = DBPROPSET_DBINIT; rgProperties[0].dwPropertyID = DBPROP_INIT_DATASOURCE; rgProperties[0].dwOptions = DBPROPOPTIONS_REQUIRED; rgProperties[0].colid = DB_NULLID; rgProperties[0].vValue.vt = VT_BSTR; V_BSTR(&rgProperties[0].vValue) = Wmioledb_SysAllocString(pstrNamespace); //======================================================= //Set properties. //======================================================= hr = pIDBProps->SetProperties(cPropertySets,rgPropertySet); if (SUCCEEDED (hr)){ pIDBProps->QueryInterface (IID_IUnknown,(LPVOID *) &pIUnknown); if (SUCCEEDED(hr)){ //=============================================== //Create this object Moniker. //=============================================== hr = CreatePointerMoniker(pIUnknown, ppIMoniker); if (FAILED(hr)){ *ppIMoniker = NULL; } } } } } SAFE_DELETE_ARRAY(pstrNamespace); //=========================================================== // Clear property values //=========================================================== VariantClear(&rgProperties[0].vValue); SAFE_RELEASE_PTR(pIClassFact); SAFE_RELEASE_PTR(pIDBProps); SAFE_RELEASE_PTR(pIUnknown); } hr = hr != S_OK ? g_pCError->PostHResult(hr,&IID_ISourcesRowset): hr; CATCH_BLOCK_HRESULT(hr,L"IParseDisplayName::ParseDisplayName"); return hr; }