Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

643 lines
21 KiB

  1. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Microsoft WMI OLE DB Provider
  4. // (C) Copyright 1999 Microsoft Corporation. All Rights Reserved.
  5. //
  6. // Enumeration Routines
  7. //
  8. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  9. #include "headers.h"
  10. #include "command.h"
  11. #include "schema.h"
  12. #include "enumerat.h"
  13. #define NAMESPACE_SEPARATOR L"\\"
  14. //////////////////////////////////////////////////////////////////////////////////////////////////////////////
  15. //
  16. // Microsoft WMI OLE DB Provider
  17. // (C) Copyright 1999 Microsoft Corporation. All Rights Reserved.
  18. //
  19. // The module contains the DLL Entry and Exit points, plus the OLE ClassFactory class for RootBinder object.
  20. //
  21. //////////////////////////////////////////////////////////////////////////////////////////////////////////////
  22. //#define DECLARE_GLOBALS
  23. //===============================================================================
  24. // Don't include everything from windows.h, but always bring in OLE 2 support
  25. //===============================================================================
  26. //#define WIN32_LEAN_AND_MEAN
  27. #define INC_OLE2
  28. //===============================================================================
  29. // Make sure constants get initialized
  30. //===============================================================================
  31. #define INITGUID
  32. #define DBINITCONSTANTS
  33. //===============================================================================
  34. // Basic Windows and OLE everything
  35. //===============================================================================
  36. #include <windows.h>
  37. //===============================================================================
  38. // OLE DB headers
  39. //===============================================================================
  40. #include "oledb.h"
  41. #include "oledberr.h"
  42. //===============================================================================
  43. // Data conversion library header
  44. //===============================================================================
  45. #include "msdadc.h"
  46. //===============================================================================
  47. // Guids for data conversion library
  48. //===============================================================================
  49. #include "msdaguid.h"
  50. //===============================================================================
  51. // GUIDs
  52. //===============================================================================
  53. #include "guids.h"
  54. //===============================================================================
  55. // Common project stuff
  56. //===============================================================================
  57. #include "headers.h"
  58. #include "binderclassfac.h"
  59. //===============================================================================
  60. // Globals
  61. //===============================================================================
  62. extern LONG g_cObj; // # of outstanding objects
  63. extern LONG g_cLock; // # of explicit locks set
  64. extern DWORD g_cAttachedProcesses; // # of attached processes
  65. extern DWORD g_dwPageSize; // System page size
  66. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  67. static const GUID* x_rgEnumeratorErrInt[] =
  68. {
  69. &IID_IParseDisplayName,
  70. &IID_ISourcesRowset,
  71. };
  72. static const ULONG x_cEnumeratorErrInt = NUMELEM(x_rgEnumeratorErrInt);
  73. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  74. #pragma warning (disable:4355)
  75. CEnumeratorNameSpace :: CEnumeratorNameSpace(LPUNKNOWN pUnkOuter): CBaseObj(BOT_ENUMERATOR,pUnkOuter),
  76. m_ISourcesRowset(this),
  77. m_IParseDisplayName(this)
  78. {
  79. m_dwStatus = 0;
  80. m_pCDataSource = NULL;
  81. m_pCDBSession = NULL;
  82. m_pISupportErrorInfo = NULL;
  83. }
  84. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  85. #pragma warning (default:4355)
  86. CEnumeratorNameSpace :: ~CEnumeratorNameSpace (void)
  87. {
  88. //==============================
  89. // Release the session
  90. //==============================
  91. SAFE_RELEASE_PTR(m_pCDBSession);
  92. //==============================
  93. // Release the data source
  94. //==============================
  95. SAFE_RELEASE_PTR(m_pCDataSource);
  96. }
  97. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  98. HRESULT CEnumeratorNameSpace::CreateDataSource()
  99. {
  100. HRESULT hr = E_FAIL;
  101. IDBInitialize * pInitialize = NULL;
  102. IDBProperties * pDBProperties = NULL;
  103. DBPROPSET rgPropertySets[1];
  104. DBPROPIDSET rgPropIDSet[1];
  105. DBPROP rgprop[1];
  106. VARIANT varValue;
  107. ULONG cPropSets = 1;
  108. CDataSource *pDataSource = NULL;
  109. memset(&rgprop[0],0,sizeof(DBPROP));
  110. memset(&rgPropertySets[0],0,sizeof(DBPROPSET));
  111. VariantInit(&varValue);
  112. try
  113. {
  114. //========================================================
  115. // Allocate a new datasource object
  116. //========================================================
  117. pDataSource = new CDataSource( NULL );
  118. }
  119. catch(...)
  120. {
  121. SAFE_RELEASE_PTR(pDataSource);
  122. throw;
  123. }
  124. if( !pDataSource ){
  125. hr = E_OUTOFMEMORY;
  126. }
  127. else
  128. {
  129. hr = pDataSource->QueryInterface(IID_IUnknown,(void **)&m_pCDataSource);
  130. //========================================================
  131. // Initialize the data source
  132. //========================================================
  133. if(SUCCEEDED(hr = ((CDataSource*)m_pCDataSource)->FInit())){
  134. if(!(FAILED(hr = m_pCDataSource->QueryInterface(IID_IDBProperties ,(void **)&pDBProperties))))
  135. {
  136. rgPropIDSet[0].cPropertyIDs = 0;
  137. rgPropIDSet[0].guidPropertySet = DBPROPSET_DBINIT;
  138. //================================================================================
  139. // Get the properties set before....
  140. //================================================================================
  141. // hr = m_pUtilProp->GetProperties(0,0,rgPropIDSet, &cPropSets,&prgPropertySets);
  142. // hr = pDBProperties->SetProperties(cPropSets,prgPropertySets);
  143. // if(FAILED(hr)){
  144. // return hr;
  145. // }
  146. //================================================================================
  147. // Always use the root namespace, & set the DBPROP_INIT_DATASOURCE property
  148. //================================================================================
  149. CVARIANT v(ROOT_NAMESPACE);
  150. rgprop[0].dwPropertyID = DBPROP_INIT_DATASOURCE;
  151. rgprop[0].vValue.vt = VT_BSTR;
  152. rgprop[0].vValue.bstrVal = v;
  153. rgPropertySets[0].rgProperties = &rgprop[0];
  154. rgPropertySets[0].cProperties = 1;
  155. rgPropertySets[0].guidPropertySet = DBPROPSET_DBINIT;
  156. if(SUCCEEDED(hr = pDBProperties->SetProperties(1,rgPropertySets)))
  157. {
  158. //================================================================================
  159. // Get the pointer to IDBInitialize interface
  160. //================================================================================
  161. if(SUCCEEDED(hr = m_pCDataSource->QueryInterface(IID_IDBInitialize, (void **)&pInitialize)))
  162. {
  163. //============================================================================
  164. // Initialize the Datasource object
  165. //============================================================================
  166. hr = pInitialize->Initialize();
  167. }
  168. // SAFE_RELEASE_PTR(m_pCDataSource);
  169. } // succeeded of SetProperties
  170. } // succeeeded of QI
  171. } // if(((CDataSource*)m_pCDataSource)-FInit()>)
  172. } // Else for if( !m_pCDataSource )
  173. return hr;
  174. }
  175. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  176. //
  177. // Initializes enumerator object. Instantiate interface implementation objects.
  178. //
  179. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  180. STDMETHODIMP CEnumeratorNameSpace::Initialize(void)
  181. {
  182. const IID* piid = &IID_ISourcesRowset;
  183. HRESULT hr = S_OK;
  184. if (!(m_dwStatus & ENK_DIDINIT)){
  185. //=========================================================
  186. // Allocate and initialize a DataSource object
  187. //=========================================================
  188. if( SUCCEEDED(hr == CreateDataSource()) ){
  189. //=====================================================
  190. // Allocate and initialize a Session object
  191. //=====================================================
  192. IDBCreateSession *pDBCreateSession = NULL;
  193. m_pISupportErrorInfo = new CImpISupportErrorInfo(this);
  194. assert(m_pCDataSource != NULL);
  195. // NTRaid:136454
  196. // 07/05/00
  197. if(m_pISupportErrorInfo)
  198. {
  199. hr = m_pCDataSource->QueryInterface(IID_IDBCreateSession,(void **)&pDBCreateSession);
  200. if( S_OK == hr ){
  201. //===============================================
  202. // Create session
  203. //===============================================
  204. hr = pDBCreateSession->CreateSession(m_pUnkOuter,IID_IUnknown,&m_pCDBSession);
  205. if( hr == S_OK ){
  206. m_dwStatus |= ENK_DIDINIT;
  207. m_pCDBSession->AddRef();
  208. }
  209. }
  210. if(pDBCreateSession){
  211. pDBCreateSession->Release();
  212. }
  213. }
  214. else
  215. {
  216. hr = E_OUTOFMEMORY;
  217. }
  218. }
  219. if(SUCCEEDED(hr))
  220. {
  221. hr = AddInterfacesForISupportErrorInfo();
  222. }
  223. }
  224. if(hr != S_OK ){
  225. g_pCError->PostWMIErrors(hr, piid,GetDataSource()->GetErrorDataPtr());
  226. SAFE_RELEASE_PTR(m_pCDataSource);
  227. SAFE_RELEASE_PTR(m_pCDBSession);
  228. }
  229. else{
  230. g_pCError->PostHResult(hr, piid);
  231. }
  232. return hr;
  233. }
  234. /////////////////////////////////////////////////////////////////////////////////////////////////////
  235. // Function to add interfaces to ISupportErrorInfo interface
  236. /////////////////////////////////////////////////////////////////////////////////////////////////////
  237. HRESULT CEnumeratorNameSpace::AddInterfacesForISupportErrorInfo()
  238. {
  239. HRESULT hr = S_OK;
  240. if(SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_ISourcesRowset)))
  241. {
  242. hr = m_pISupportErrorInfo->AddInterfaceID(IID_IParseDisplayName);
  243. }
  244. return hr;
  245. }
  246. /////////////////////////////////////////////////////////////////////////////////////////////////////////
  247. STDMETHODIMP_(ULONG) CEnumeratorNameSpace::AddRef(void)
  248. {
  249. return InterlockedIncrement( (long*) &m_cRef);
  250. }
  251. /////////////////////////////////////////////////////////////////////////////////////////////////////////
  252. STDMETHODIMP_(ULONG) CEnumeratorNameSpace::Release(void)
  253. {
  254. ULONG cRef = InterlockedDecrement( (long*) &m_cRef);
  255. if ( !cRef )
  256. delete this;
  257. return cRef;
  258. }
  259. /////////////////////////////////////////////////////////////////////////////////////////////////////////
  260. STDMETHODIMP CEnumeratorNameSpace::QueryInterface( REFIID riid, LPVOID *ppv )
  261. {
  262. HRESULT hr = S_OK;
  263. //===========================================
  264. // Is the pointer bad?
  265. //===========================================
  266. if ( ppv == NULL )
  267. {
  268. hr = E_INVALIDARG;
  269. }
  270. {
  271. //===========================================
  272. // This is the non-delegating IUnknown
  273. // implementation
  274. //===========================================
  275. if ( riid == IID_IUnknown )
  276. *ppv = (LPVOID)this;
  277. else if ( riid == IID_ISourcesRowset )
  278. *ppv = (LPVOID)&m_ISourcesRowset;
  279. else if ( riid == IID_IParseDisplayName )
  280. *ppv = (LPVOID)&m_IParseDisplayName;
  281. else if ( riid == IID_ISupportErrorInfo )
  282. *ppv = (LPVOID)m_pISupportErrorInfo;
  283. else
  284. //=======================================
  285. // Place NULL in *ppv in case of failure
  286. //=======================================
  287. *ppv = NULL;
  288. if ( *ppv ){
  289. ((LPUNKNOWN)*ppv)->AddRef();
  290. hr = S_OK;
  291. }
  292. else
  293. {
  294. hr = E_NOINTERFACE;
  295. }
  296. }
  297. return hr;
  298. }
  299. /////////////////////////////////////////////////////////////////////////////////////////////////////////
  300. STDMETHODIMP_(ULONG) CImpISourcesRowset::AddRef(void)
  301. {
  302. InterlockedIncrement((long*)&m_cRef);
  303. return m_pCEnumeratorNameSpace->AddRef();
  304. }
  305. /////////////////////////////////////////////////////////////////////////////////////////////////////////
  306. STDMETHODIMP_(ULONG) CImpISourcesRowset::Release(void)
  307. {
  308. InterlockedDecrement((long*)&m_cRef);
  309. return m_pCEnumeratorNameSpace->Release();
  310. }
  311. /////////////////////////////////////////////////////////////////////////////////////////////////////////
  312. STDMETHODIMP CImpISourcesRowset::QueryInterface( REFIID riid, LPVOID * ppv )
  313. {
  314. return m_pCEnumeratorNameSpace->QueryInterface(riid, ppv);
  315. }
  316. /////////////////////////////////////////////////////////////////////////////////////////////////////////
  317. //
  318. // Instantiate a rowset with a list of data sources.
  319. //
  320. /////////////////////////////////////////////////////////////////////////////////////////////////////////
  321. STDMETHODIMP CImpISourcesRowset::GetSourcesRowset( IUnknown* pUnkOuter, REFIID riid, ULONG cPropertySets,DBPROPSET rgPropertySets[], IUnknown** ppIRowset )
  322. {
  323. HRESULT hr = E_INVALIDARG;
  324. CSchema_ISourcesRowset *pCSchema = NULL;
  325. CSetStructuredExceptionHandler seh;
  326. TRY_BLOCK;
  327. //=====================================================================
  328. // Check parameters
  329. //=====================================================================
  330. assert( m_pCEnumeratorNameSpace );
  331. //=====================================================================
  332. // NULL out-params in case of error
  333. //=====================================================================
  334. //===============================================================
  335. // Clear previous Error Object for this thread
  336. //===============================================================
  337. g_pCError->ClearErrorInfo();
  338. if(ppIRowset)
  339. {
  340. *ppIRowset = NULL;
  341. }
  342. //=====================================================================
  343. // Check Arguments
  344. //=====================================================================
  345. if ( riid == IID_NULL){
  346. hr = E_NOINTERFACE ;
  347. }
  348. else
  349. if ( (pUnkOuter) && (riid != IID_IUnknown) ){ // We do not allow the riid to be anything other than IID_IUnknown for aggregation
  350. hr = DB_E_NOAGGREGATION ;
  351. }
  352. else
  353. {
  354. //===============================================================
  355. // Serialize access to this object.
  356. //===============================================================
  357. CAutoBlock block(m_pCEnumeratorNameSpace->GetCriticalSection());
  358. //===============================================================
  359. // Spec-defined error checks.
  360. //===============================================================
  361. if (!ppIRowset || (cPropertySets && !rgPropertySets)){
  362. hr = E_INVALIDARG ;
  363. }
  364. else{
  365. //===========================================================
  366. // The outer object must explicitly ask for IUnknown
  367. //===========================================================
  368. if (pUnkOuter != NULL && riid != IID_IUnknown){
  369. hr = DB_E_NOAGGREGATION;
  370. }
  371. else{
  372. if (SUCCEEDED(hr = m_pCEnumeratorNameSpace->Initialize())){
  373. try
  374. {
  375. pCSchema = new CSchema_ISourcesRowset(pUnkOuter,m_pCEnumeratorNameSpace->GetSession());
  376. }
  377. catch(...)
  378. {
  379. SAFE_DELETE_PTR(pCSchema);
  380. throw;
  381. }
  382. if (!pCSchema){
  383. hr = E_OUTOFMEMORY;
  384. }
  385. else{
  386. hr = pCSchema->FInit(cPropertySets, rgPropertySets, riid, pUnkOuter, ppIRowset,NULL);
  387. }
  388. }
  389. }
  390. }
  391. if( FAILED(hr ) ){
  392. SAFE_RELEASE_PTR( pCSchema );
  393. *ppIRowset = NULL;
  394. }
  395. } // else
  396. hr = hr != S_OK ? g_pCError->PostHResult(hr,&IID_ISourcesRowset): hr;
  397. CATCH_BLOCK_HRESULT(hr,L"ISourcesRowset::GetSourcesRowset");
  398. return hr;
  399. }
  400. /////////////////////////////////////////////////////////////////////////////////////////////////////////
  401. //
  402. // CImpIParseDisplayName
  403. //
  404. /////////////////////////////////////////////////////////////////////////////////////////////////////////
  405. STDMETHODIMP_(ULONG) CImpIParseDisplayName::AddRef(void)
  406. {
  407. InterlockedIncrement((long*)&m_cRef);
  408. return m_pCEnumeratorNameSpace->AddRef();
  409. }
  410. /////////////////////////////////////////////////////////////////////////////////////////////////////////
  411. STDMETHODIMP_(ULONG) CImpIParseDisplayName::Release(void)
  412. {
  413. InterlockedDecrement((long*)&m_cRef);
  414. return m_pCEnumeratorNameSpace->Release();
  415. }
  416. /////////////////////////////////////////////////////////////////////////////////////////////////////////
  417. STDMETHODIMP CImpIParseDisplayName::QueryInterface( REFIID riid, LPVOID * ppv )
  418. {
  419. return m_pCEnumeratorNameSpace->QueryInterface(riid, ppv);
  420. }
  421. /////////////////////////////////////////////////////////////////////////////////////////////////////////
  422. //
  423. // Function creates moniker according to the name passed to it.
  424. //
  425. /////////////////////////////////////////////////////////////////////////////////////////////////////////
  426. STDMETHODIMP CImpIParseDisplayName::ParseDisplayName( IBindCtx *pbc, WCHAR *pwszDisplayName,
  427. ULONG *pchEaten, IMoniker **ppIMoniker)
  428. {
  429. //===========================================================
  430. //
  431. // Instantiate Data Source Object.
  432. // Set all interesting properties.
  433. // Initialize object.
  434. // Create pointer moniker and pass it out.
  435. //
  436. // Need to find out a way to use IBindCtx.
  437. //
  438. //===========================================================
  439. HRESULT hr = S_OK;
  440. CSetStructuredExceptionHandler seh;
  441. TRY_BLOCK;
  442. if (ppIMoniker)
  443. {
  444. *ppIMoniker = NULL;
  445. }
  446. if (!pwszDisplayName || !pchEaten){
  447. hr = MK_E_NOOBJECT;
  448. // return g_pCError->PostHResult((MK_E_NOOBJECT), &IID_IParseDisplayName);
  449. }
  450. else
  451. if (!ppIMoniker){
  452. hr = E_UNEXPECTED;
  453. // return g_pCError->PostHResult((E_UNEXPECTED),&IID_IParseDisplayName);
  454. }
  455. else
  456. {
  457. IClassFactory * pIClassFact=NULL;
  458. IDBProperties * pIDBProps=NULL;
  459. IUnknown * pIUnknown=NULL;
  460. //===========================================================
  461. //Define Property Structures.
  462. //===========================================================
  463. ULONG cPropertySets;
  464. DBPROPSET rgPropertySet[1];
  465. DBPROP rgProperties[1];
  466. //===========================================================
  467. // Clear Error Messages on current thread
  468. //===========================================================
  469. g_pCError->ClearErrorInfo();
  470. //===========================================================
  471. // Initialize property values
  472. //===========================================================
  473. VariantInit(&rgProperties[0].vValue);
  474. hr = CoCreateInstance( CLSID_WMIOLEDB,NULL, CLSCTX_INPROC_SERVER, IID_IDBProperties, (void**)&pIDBProps);
  475. CURLParser urlParser;
  476. CBSTR strTemp,strKey;
  477. VARIANT varKeyVal;
  478. int lSizeToAlloc = 0;
  479. WCHAR *pstrNamespace = NULL;
  480. VariantInit(&varKeyVal);
  481. strTemp.SetStr(pwszDisplayName);
  482. urlParser.SetPath(strTemp);
  483. strTemp.Clear();
  484. urlParser.GetNameSpace((BSTR &)strTemp);
  485. strKey.SetStr(L"Name");
  486. // Get the Name of the NameSpace
  487. urlParser.GetKeyValue(strKey,varKeyVal);
  488. lSizeToAlloc = (SysStringLen(varKeyVal.bstrVal) +
  489. SysStringLen(strTemp) +
  490. wcslen(NAMESPACE_SEPARATOR) + 1 ) * sizeof(WCHAR);
  491. try
  492. {
  493. pstrNamespace = new WCHAR[lSizeToAlloc];
  494. }
  495. catch(...)
  496. {
  497. SAFE_DELETE_ARRAY(pstrNamespace);
  498. throw;
  499. }
  500. if(!pstrNamespace)
  501. {
  502. hr = E_OUTOFMEMORY;
  503. }
  504. else
  505. {
  506. // Frame the Namespace string
  507. memset(pstrNamespace,0,lSizeToAlloc * sizeof(WCHAR));
  508. memcpy(pstrNamespace,strTemp,SysStringLen(strTemp) * sizeof(WCHAR));
  509. wcscat(pstrNamespace,NAMESPACE_SEPARATOR);
  510. memcpy((pstrNamespace + wcslen(pstrNamespace)),varKeyVal.bstrVal,SysStringLen(varKeyVal.bstrVal) * sizeof(WCHAR));
  511. if (SUCCEEDED(hr)){
  512. //=======================================================
  513. //Set Init properties.
  514. //=======================================================
  515. cPropertySets = 1;
  516. rgPropertySet[0].rgProperties = rgProperties;
  517. rgPropertySet[0].cProperties = 1;
  518. rgPropertySet[0].guidPropertySet = DBPROPSET_DBINIT;
  519. rgProperties[0].dwPropertyID = DBPROP_INIT_DATASOURCE;
  520. rgProperties[0].dwOptions = DBPROPOPTIONS_REQUIRED;
  521. rgProperties[0].colid = DB_NULLID;
  522. rgProperties[0].vValue.vt = VT_BSTR;
  523. V_BSTR(&rgProperties[0].vValue) = Wmioledb_SysAllocString(pstrNamespace);
  524. //=======================================================
  525. //Set properties.
  526. //=======================================================
  527. hr = pIDBProps->SetProperties(cPropertySets,rgPropertySet);
  528. if (SUCCEEDED (hr)){
  529. pIDBProps->QueryInterface (IID_IUnknown,(LPVOID *) &pIUnknown);
  530. if (SUCCEEDED(hr)){
  531. //===============================================
  532. //Create this object Moniker.
  533. //===============================================
  534. hr = CreatePointerMoniker(pIUnknown, ppIMoniker);
  535. if (FAILED(hr)){
  536. *ppIMoniker = NULL;
  537. }
  538. }
  539. }
  540. }
  541. }
  542. SAFE_DELETE_ARRAY(pstrNamespace);
  543. //===========================================================
  544. // Clear property values
  545. //===========================================================
  546. VariantClear(&rgProperties[0].vValue);
  547. SAFE_RELEASE_PTR(pIClassFact);
  548. SAFE_RELEASE_PTR(pIDBProps);
  549. SAFE_RELEASE_PTR(pIUnknown);
  550. }
  551. hr = hr != S_OK ? g_pCError->PostHResult(hr,&IID_ISourcesRowset): hr;
  552. CATCH_BLOCK_HRESULT(hr,L"IParseDisplayName::ParseDisplayName");
  553. return hr;
  554. }