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.

4421 lines
135 KiB

  1. //***************************************************************************
  2. //
  3. // Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
  4. //
  5. // WBEMGLUE.CPP
  6. //
  7. // Purpose: Implementation of CWbemProviderGlue class
  8. //
  9. //***************************************************************************
  10. #include "precomp.h"
  11. #include <assertbreak.h>
  12. #include <eventProvider.h>
  13. #include <FRQueryEx.h>
  14. #include <cnvmacros.h>
  15. #include <BrodCast.h>
  16. #include <cominit.h>
  17. #include <StopWatch.h>
  18. #include <comdef.h>
  19. #include <SmartPtr.h>
  20. #include <lmcons.h>
  21. #define SECURITY_WIN32
  22. #include <sspi.h>
  23. #include <Secext.h>
  24. #include "FWStrings.h"
  25. #include "MultiPlat.h"
  26. #include <AutoImpRevert.h>
  27. #include <lockwrap.h>
  28. #include <winbasep.h>
  29. class CWbemGlueImpersonation
  30. {
  31. CWbemGlueImpersonation ( const CWbemGlueImpersonation& ) {}
  32. HRESULT m_hr;
  33. public:
  34. CWbemGlueImpersonation () : m_hr ( E_FAIL )
  35. {
  36. m_hr = CWbemProviderGlue::CheckImpersonationLevel ();
  37. }
  38. ~CWbemGlueImpersonation ()
  39. {
  40. if SUCCEEDED ( m_hr )
  41. {
  42. WbemCoRevertToSelf ();
  43. }
  44. }
  45. HRESULT IsImpersonated () const
  46. {
  47. return m_hr;
  48. }
  49. };
  50. #define GLUETIMEOUT WBEM_INFINITE //(3 * 60 * 1000)
  51. // Used in ASSERT_BREAK to give meaningful messages
  52. #define DEPRECATED 1
  53. #define MEMORY_EXHAUSTED 0
  54. #define FRAMEWORK_EXCEPTION 0
  55. #define UNSPECIFIED_EXCEPTION 0
  56. #define STRUCTURED_EXCEPTION 0
  57. #define DUPLICATE_RELEASE 0
  58. #define IMPERSONATION_REVERTED 0
  59. #define UNNECESSARY_CWBEMPROVIDERGLUE_INSTANCE 0
  60. // Initialize Statics
  61. STRING2LPVOID CWbemProviderGlue::s_providersmap;
  62. CCritSec CWbemProviderGlue::s_csFactoryMap;
  63. PTR2PLONG CWbemProviderGlue::s_factorymap;
  64. CCritSec CWbemProviderGlue::s_csProviderMap;
  65. CCritSec CWbemProviderGlue::m_csStatusObject;
  66. IWbemClassObject *CWbemProviderGlue::m_pStatusObject = NULL;
  67. BOOL CWbemProviderGlue::s_bInitted = FALSE;
  68. DWORD CWbemProviderGlue::s_dwPlatform = 0;
  69. DWORD CWbemProviderGlue::s_dwMajorVersion = 0;
  70. WCHAR CWbemProviderGlue::s_wstrCSDVersion[128] = {0};
  71. long CWbemProviderGlue::s_lObjects = 0;
  72. // Static Provider we use to initialize, uninitialize our static
  73. // data. We should be able to assume at Construct/Destruct time that
  74. // we (the DLL) are being loaded/unloaded.
  75. // later on -- we should, but we can't. Current model is that we
  76. // uninitialize when the last DLL that we service has called DLLLogoff,
  77. // which had better be in response to "DllCanUnloadNow"
  78. CWbemProviderGlue g_wbemprovider;
  79. /////////////////////////////////////////////////////////////////////
  80. //
  81. // Function: CWbemProviderGlue::CWbemProviderGlue
  82. //
  83. // Class CTor. Uses static initialization functon to get static data
  84. // ready if this is the first instance of our object.
  85. //
  86. // Inputs: None
  87. //
  88. // Outputs: None.
  89. //
  90. // Returns: None.
  91. //
  92. // Comments:
  93. //
  94. /////////////////////////////////////////////////////////////////////
  95. CWbemProviderGlue::CWbemProviderGlue()
  96. : m_strNamespace(),
  97. m_lRefCount(0),
  98. m_pCount(NULL),
  99. m_pServices(NULL)
  100. {
  101. Init();
  102. }
  103. CWbemProviderGlue::CWbemProviderGlue(PLONG pCount)
  104. : m_strNamespace(),
  105. m_lRefCount(0),
  106. m_pCount(pCount),
  107. m_pServices(NULL)
  108. {
  109. CWbemProviderGlue::IncrementMapCount(pCount);
  110. }
  111. /////////////////////////////////////////////////////////////////////
  112. //
  113. // Function: CWbemProviderGlue::~CWbemProviderGlue
  114. //
  115. // Class DTor.
  116. //
  117. // Inputs: None
  118. //
  119. // Outputs: None.
  120. //
  121. // Returns: None.
  122. //
  123. // Comments:
  124. //
  125. /////////////////////////////////////////////////////////////////////
  126. CWbemProviderGlue::~CWbemProviderGlue()
  127. {
  128. // Note that the item we are destructing here was not added in
  129. // the constructor, but in Initialize().
  130. if (m_pServices)
  131. {
  132. m_pServices->Release();
  133. }
  134. if (m_pCount != NULL) // Indicates the static instance
  135. {
  136. if (DecrementMapCount(m_pCount) == 0)
  137. {
  138. FlushAll();
  139. }
  140. }
  141. else
  142. {
  143. UnInit();
  144. }
  145. }
  146. /////////////////////////////////////////////////////////////////////
  147. //
  148. // Function: CWbemProviderGlue::Init
  149. //
  150. // Static initialization function for initializing critical sections
  151. // and such for making our static data thread-safe.
  152. //
  153. // Inputs: None.
  154. //
  155. // Outputs: None.
  156. //
  157. // Returns: None.
  158. //
  159. // Comments: Because we are protecting static data, we are using
  160. // a named mutex. Construction and Destruction of object
  161. // instances should call these functions.
  162. //
  163. /////////////////////////////////////////////////////////////////////
  164. void CWbemProviderGlue::Init( void )
  165. {
  166. LogMessage(IDS_GLUEINIT);
  167. if (!s_bInitted)
  168. {
  169. // Note that we *have* to use the ansi version at this point,
  170. // since this is where we decide whether to use the ansi functions
  171. // or the unicode ones.
  172. OSVERSIONINFOA OsVersionInfoA;
  173. OsVersionInfoA.dwOSVersionInfoSize = sizeof (OSVERSIONINFOA) ;
  174. GetVersionExA(&OsVersionInfoA);
  175. s_dwPlatform = OsVersionInfoA.dwPlatformId;
  176. s_dwMajorVersion = OsVersionInfoA.dwMajorVersion;
  177. if (OsVersionInfoA.szCSDVersion == NULL)
  178. {
  179. s_wstrCSDVersion[0] = L'\0';
  180. }
  181. else
  182. {
  183. bool t_ConversionFailure = false ;
  184. WCHAR *wcsBuffer = NULL ;
  185. ANSISTRINGTOWCS(OsVersionInfoA.szCSDVersion, wcsBuffer, t_ConversionFailure );
  186. if ( ! t_ConversionFailure )
  187. {
  188. if ( wcsBuffer )
  189. {
  190. wcscpy(s_wstrCSDVersion, wcsBuffer);
  191. }
  192. else
  193. {
  194. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  195. }
  196. }
  197. else
  198. {
  199. // Should do something here since we know version is not initialised.
  200. }
  201. }
  202. s_bInitted = TRUE;
  203. }
  204. else
  205. {
  206. ASSERT_BREAK(UNNECESSARY_CWBEMPROVIDERGLUE_INSTANCE);
  207. }
  208. }
  209. /////////////////////////////////////////////////////////////////////
  210. //
  211. // Function: CWbemProviderGlue::UnInit
  212. //
  213. // Static cleanup function for cleaning up critical sections
  214. // and such for making our static data thread-safe.
  215. //
  216. // Inputs: None.
  217. //
  218. // Outputs: None.
  219. //
  220. // Returns: None.
  221. //
  222. // Comments: Because we are protecting static data, we are using
  223. // a named mutex. Construction and Destruction of object
  224. // instances should call these functions.
  225. //
  226. /////////////////////////////////////////////////////////////////////
  227. void CWbemProviderGlue::UnInit( void )
  228. {
  229. LogMessage(IDS_GLUEUNINIT);
  230. }
  231. /////////////////////////////////////////////////////////////////////
  232. //
  233. // Function: CWbemProviderGlue::GetStaticMutex
  234. //
  235. // Creates and returns an instance of the named mutex used to
  236. // protect our static initialization functions.
  237. //
  238. // Inputs: None.
  239. //
  240. // Outputs: None.
  241. //
  242. // Returns: None.
  243. //
  244. // Comments: The mutex, although it is named, makes the process
  245. // id part of the name, guaranteeing that it is still
  246. // unique across processes.
  247. //
  248. /////////////////////////////////////////////////////////////////////
  249. /////////////////////////////////////////////////////////////////////
  250. //
  251. // Function: CWbemProviderGlue::QueryInterface
  252. //
  253. // COM function called to ask us if we support a particular
  254. // face type. If so, we addref ourselves and return the
  255. // ourselves as an LPVOID.
  256. //
  257. // Inputs: REFIID riid - Interface being queried for.
  258. //
  259. // Outputs: LPVOID FAR* ppvObj - Interface pointer.
  260. //
  261. // Returns: None.
  262. //
  263. // Comments: The only interfaces we support are IID_IUnknown and
  264. // IID_IWbemServices.
  265. //
  266. /////////////////////////////////////////////////////////////////////
  267. STDMETHODIMP CWbemProviderGlue::QueryInterface( REFIID riid, LPVOID FAR *ppvObj )
  268. {
  269. LogMessage(L"CWbemProviderGlue::QueryInterface");
  270. if (IsEqualIID(riid, IID_IUnknown))
  271. {
  272. *ppvObj = (IWbemServices *) this;
  273. }
  274. else if (IsEqualIID(riid, IID_IWbemServices))
  275. {
  276. *ppvObj = (IWbemServices *) this;
  277. }
  278. else if (IsEqualIID(riid, IID_IWbemProviderInit))
  279. {
  280. *ppvObj = (IWbemProviderInit *) this;
  281. }
  282. else
  283. {
  284. try
  285. {
  286. *ppvObj = NULL ;
  287. if (IsVerboseLoggingEnabled())
  288. {
  289. WCHAR wcID[128];
  290. StringFromGUID2(riid, wcID, 128);
  291. LogMessage2(L"CWbemProviderGlue::QueryInterface - unsupported interface (%s)", wcID);
  292. }
  293. }
  294. catch ( ... )
  295. {
  296. }
  297. return ResultFromScode(E_NOINTERFACE) ;
  298. }
  299. AddRef() ;
  300. return NOERROR ;
  301. }
  302. /////////////////////////////////////////////////////////////////////
  303. //
  304. // Function: CWbemProviderGlue::AddRef
  305. //
  306. // Increments the reference count on this object.
  307. //
  308. // Inputs: None.
  309. //
  310. // Outputs: None.
  311. //
  312. // Returns: ULONG - Our Reference Count.
  313. //
  314. // Comments: Requires that a correponding call to Release be
  315. // performed.
  316. //
  317. /////////////////////////////////////////////////////////////////////
  318. ULONG CWbemProviderGlue::AddRef( void )
  319. {
  320. CSetStructuredExceptionHandler t_ExceptionHandler;
  321. try
  322. {
  323. if (IsVerboseLoggingEnabled())
  324. {
  325. // this will be an approximation because another thread could come through...
  326. LogMessage2(L"CWbemProviderGlue::AddRef, count is (approx) %d", m_lRefCount +1);
  327. };
  328. }
  329. catch ( ... )
  330. {
  331. }
  332. // InterlockedIncrement does not necessarily return the
  333. // correct value, only whether the value is <, =, > 0.
  334. // However it is guaranteed threadsafe.
  335. return InterlockedIncrement( &m_lRefCount );
  336. }
  337. /////////////////////////////////////////////////////////////////////
  338. //
  339. // Function: CWbemProviderGlue::Intialize
  340. //
  341. // Inputs: Many.
  342. //
  343. // Outputs: None.
  344. //
  345. // Returns:
  346. //
  347. // Comments: any global initializations, esp those that call CIMOM should go here.
  348. //
  349. /////////////////////////////////////////////////////////////////////
  350. HRESULT CWbemProviderGlue::Initialize(
  351. /* [in] */ LPWSTR pszUser,
  352. /* [in] */ LONG lFlags,
  353. /* [in] */ LPWSTR pszNamespace,
  354. /* [in] */ LPWSTR pszLocale,
  355. /* [in] */ IWbemServices __RPC_FAR *pNamespace,
  356. /* [in] */ IWbemContext __RPC_FAR *pCtx,
  357. /* [in] */ IWbemProviderInitSink __RPC_FAR *pInitSink)
  358. {
  359. CSetStructuredExceptionHandler t_ExceptionHandler;
  360. HRESULT hr = WBEM_S_NO_ERROR;
  361. try
  362. {
  363. if (IsVerboseLoggingEnabled())
  364. {
  365. LogMessage3(L"%s(%s)", IDS_GLUEINITINTERFACE, pszNamespace);
  366. }
  367. }
  368. catch ( ... )
  369. {
  370. }
  371. if ( (NULL != pszNamespace) && (NULL != pNamespace) )
  372. {
  373. try
  374. {
  375. // this may come back to bite me
  376. // CIMOM promises that this will only be called on one thread, once per object
  377. // and that no queries will be issued until after initialize is called.
  378. // therefore - I don't need a critical section, here -
  379. m_strNamespace = pszNamespace;
  380. m_strNamespace.MakeUpper();
  381. pNamespace->AddRef();
  382. m_pServices = pNamespace;
  383. }
  384. catch ( CFramework_Exception e_FR )
  385. {
  386. ASSERT_BREAK(FRAMEWORK_EXCEPTION);
  387. hr = WBEM_E_PROVIDER_FAILURE;
  388. }
  389. catch ( CHeap_Exception e_HE )
  390. {
  391. ASSERT_BREAK(MEMORY_EXHAUSTED);
  392. hr = WBEM_E_OUT_OF_MEMORY;
  393. }
  394. catch(CStructured_Exception e_SE)
  395. {
  396. ASSERT_BREAK(STRUCTURED_EXCEPTION);
  397. hr = WBEM_E_PROVIDER_FAILURE;
  398. }
  399. catch ( ... )
  400. {
  401. ASSERT_BREAK(UNSPECIFIED_EXCEPTION);
  402. hr = WBEM_E_PROVIDER_FAILURE;
  403. }
  404. }
  405. else
  406. {
  407. hr = WBEM_E_FAILED;
  408. }
  409. if (pInitSink)
  410. {
  411. pInitSink->SetStatus(hr, 0);
  412. hr = WBEM_S_NO_ERROR;
  413. }
  414. return hr;
  415. }
  416. /////////////////////////////////////////////////////////////////////
  417. //
  418. // Function: CWbemProviderGlue::Release
  419. //
  420. // Decrements the reference count on this object.
  421. //
  422. // Inputs: None.
  423. //
  424. // Outputs: None.
  425. //
  426. // Returns: ULONG - Our Reference Count.
  427. //
  428. // Comments: When the ref count hits zero, the object is deleted.
  429. //
  430. /////////////////////////////////////////////////////////////////////
  431. ULONG CWbemProviderGlue::Release()
  432. {
  433. // InterlockedDecrement does not necessarily return the
  434. // correct value, only whether the value is <, =, > 0.
  435. // However it is guaranteed threadsafe.
  436. // We want to hold the value locally in case two threads
  437. // Release at the same time and one gets a final release,
  438. // and deletes, leaving a potential window in which a thread
  439. // deletes the object before the other returns and tries to
  440. // reference the value from within the deleted object.
  441. CSetStructuredExceptionHandler t_ExceptionHandler;
  442. ULONG nRet = InterlockedDecrement( &m_lRefCount );
  443. try
  444. {
  445. if (IsVerboseLoggingEnabled())
  446. {
  447. LogMessage2(L"CWbemProviderGlue::Release, count is (approx) %d", m_lRefCount);
  448. }
  449. }
  450. catch ( ... )
  451. {
  452. }
  453. if( 0 == nRet )
  454. {
  455. try
  456. {
  457. LogMessage(IDS_GLUEREFCOUNTZERO);
  458. }
  459. catch ( ... )
  460. {
  461. }
  462. delete this;
  463. } else if (nRet > 0x80000000)
  464. {
  465. ASSERT_BREAK(DUPLICATE_RELEASE);
  466. }
  467. return nRet;
  468. }
  469. /////////////////////////////////////////////////////////////////////
  470. //
  471. // Function: CWbemProviderGlue::FlushAll
  472. //
  473. // Inputs: voidness
  474. //
  475. // Outputs: more voidness
  476. //
  477. // Returns: see above
  478. //
  479. // Comments: flushes caches, calls all of the provider's flushes.
  480. // no need to flush event providers map, flush will be
  481. // called on the provider pointer
  482. //
  483. /////////////////////////////////////////////////////////////////////
  484. void CWbemProviderGlue::FlushAll(void)
  485. {
  486. PROVIDERPTRS::iterator setIter;
  487. // We DEFINITELY want to protect the Map while this is running!
  488. LockProviderMap();
  489. try
  490. {
  491. // pProvider doesn't get addref'ed, so doesn't need to be released
  492. Provider *pProvider = NULL;
  493. CLockWrapper lockwrap(m_csFlushPtrs);
  494. for (setIter = m_FlushPtrs.begin(); setIter != m_FlushPtrs.end(); setIter++)
  495. {
  496. pProvider = (Provider*) *setIter;
  497. if ( pProvider != NULL )
  498. {
  499. // If one provider poops out, try the others.
  500. try
  501. {
  502. pProvider->Flush();
  503. }
  504. catch ( ... )
  505. {
  506. }
  507. }
  508. }
  509. m_FlushPtrs.clear();
  510. }
  511. catch ( ... )
  512. {
  513. UnlockProviderMap();
  514. throw;
  515. }
  516. UnlockProviderMap();
  517. if (m_pStatusObject)
  518. {
  519. m_csStatusObject.Enter();
  520. if (m_pStatusObject)
  521. {
  522. m_pStatusObject->Release();
  523. m_pStatusObject = NULL;
  524. }
  525. m_csStatusObject.Leave();
  526. }
  527. }
  528. // SetStatusObject
  529. // sets the properties in the extended status object so that it can be returned when
  530. // the glue layer calls SetStatus at the end of the method invocation.
  531. // will return false if the status object has already been filled.
  532. // (first one in wins)
  533. bool CWbemProviderGlue::SetStatusObject(
  534. MethodContext *pContext,
  535. LPCWSTR pNamespace,
  536. LPCWSTR pDescription,
  537. HRESULT hr,
  538. const SAFEARRAY *pPrivilegesNotHeld,/* = NULL */
  539. const SAFEARRAY *pPrivilegesRequired/* = NULL */
  540. )
  541. {
  542. bool bRet = false;
  543. ASSERT_BREAK(pContext != NULL);
  544. if (pContext)
  545. {
  546. IWbemClassObjectPtr pObj ( GetStatusObject(pContext, pNamespace), false );
  547. if (pObj != NULL)
  548. {
  549. // Variant_t handles the VariantInit/VariantClear
  550. variant_t v;
  551. pContext->SetStatusObject(pObj);
  552. // set hresult ("StatusCode")
  553. v.vt = VT_I4;
  554. v.lVal = (long)hr;
  555. pObj->Put(IDS_STATUSCODE, 0, &v, NULL);
  556. v.Clear();
  557. // set description
  558. if (pDescription)
  559. {
  560. v = pDescription;
  561. if (v.bstrVal != NULL)
  562. {
  563. bRet = SUCCEEDED(pObj->Put(IDS_DESCRIPTION, 0, &v, NULL));
  564. }
  565. else
  566. {
  567. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  568. }
  569. v.Clear();
  570. }
  571. // privileges properties
  572. if (pPrivilegesNotHeld)
  573. {
  574. SAFEARRAY *pSafeArray = NULL;
  575. // blithy casting away the const...
  576. if ( SUCCEEDED ( SafeArrayCopy ((SAFEARRAY*)pPrivilegesNotHeld, &pSafeArray ) ) )
  577. {
  578. v.vt = VT_BSTR | VT_ARRAY;
  579. v.parray = pSafeArray;
  580. pObj->Put(IDS_PRIVILEGESNOTHELD, 0, &v, NULL);
  581. v.Clear();
  582. }
  583. else
  584. {
  585. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  586. }
  587. }
  588. if (pPrivilegesRequired)
  589. {
  590. SAFEARRAY *pSafeArray = NULL;
  591. // blithy casting away the const...
  592. if ( SUCCEEDED ( SafeArrayCopy ((SAFEARRAY*)pPrivilegesRequired, &pSafeArray ) ) )
  593. {
  594. v.vt = VT_BSTR | VT_ARRAY;
  595. v.parray = pSafeArray;
  596. pObj->Put(IDS_PRIVILEGESREQUIRED, 0, &v, NULL);
  597. v.Clear();
  598. }
  599. else
  600. {
  601. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  602. }
  603. }
  604. }
  605. }
  606. return bRet;
  607. }
  608. IWbemClassObject *CWbemProviderGlue::GetStatusObject(
  609. MethodContext *pContext,
  610. LPCWSTR pNamespace
  611. )
  612. {
  613. ASSERT_BREAK(pContext != NULL);
  614. IWbemClassObject *pStatusObj = NULL;
  615. if (pContext != NULL)
  616. {
  617. // first time in, we cache the class object
  618. if (!m_pStatusObject)
  619. {
  620. m_csStatusObject.Enter();
  621. // check again - someone might have snuck in!
  622. if (!m_pStatusObject)
  623. {
  624. IWbemServicesPtr pSrvc;
  625. IWbemContextPtr pWbemContext (pContext->GetIWBEMContext(), false);
  626. pSrvc.Attach ( GetNamespaceConnection( pNamespace, pContext ) ) ;
  627. if ( pSrvc )
  628. {
  629. // not checking return code, error object should be NULL on error
  630. pSrvc->GetObject( bstr_t( IDS_WIN32PRIVILEGESSTATUS ), 0, pWbemContext, &m_pStatusObject, NULL );
  631. }
  632. }
  633. m_csStatusObject.Leave();
  634. }
  635. if (m_pStatusObject)
  636. m_pStatusObject->SpawnInstance(0, &pStatusObj);
  637. }
  638. else
  639. {
  640. LogErrorMessage(L"NULL parameter to GetStatusObject");
  641. }
  642. return pStatusObj;
  643. }
  644. /////////////////////////////////////////////////////////////////////
  645. //
  646. // Function: CWbemProviderGlue::ExecQueryAsync
  647. //
  648. // Place holder for the ExecQuery function.
  649. //
  650. // Inputs: const BSTR QueryFormat - Query Format String
  651. // const BSTR Query - The actual query
  652. // long lFlags - Additional flags.
  653. // IWbemContext __RPC_FAR *pCtx - Context we were called in.
  654. // IWbemObjectSink FAR *pResponseHandler - Response Handler
  655. //
  656. // Outputs: None.
  657. //
  658. // Returns: ULONG - Our Reference Count.
  659. //
  660. // Comments:
  661. //
  662. /////////////////////////////////////////////////////////////////////
  663. HRESULT CWbemProviderGlue::ExecQueryAsync(
  664. const BSTR QueryFormat,
  665. const BSTR Query,
  666. long lFlags,
  667. IWbemContext __RPC_FAR *pCtx,
  668. IWbemObjectSink FAR *pResponseHandler
  669. )
  670. {
  671. // make sure we don't disappear while running
  672. AddRef();
  673. CSetStructuredExceptionHandler t_ExceptionHandler;
  674. #ifdef PROVIDER_INSTRUMENTATION
  675. StopWatch stopWatch(CHString(IDS_EXECQUERY) + CHString(Query));
  676. stopWatch.Start(StopWatch::FrameworkTimer);
  677. #endif
  678. HRESULT hr = WBEM_S_NO_ERROR;
  679. IWbemClassObjectPtr pStatusObject;
  680. try
  681. {
  682. if (IsVerboseLoggingEnabled())
  683. {
  684. LogMessage3(L"%s%s", IDS_EXECQUERY, Query);
  685. }
  686. // Now create an External Method Context object and go to town
  687. ExternalMethodContextPtr pContext (new ExternalMethodContext( pResponseHandler, pCtx, this ), false);
  688. #ifdef PROVIDER_INSTRUMENTATION
  689. pContext->pStopWatch = &stopWatch;
  690. #endif
  691. if (pContext != NULL)
  692. {
  693. CFrameworkQueryEx CQuery;
  694. // hr = CQuery.InitEx(QueryFormat, Query, lFlags, m_strNamespace);
  695. hr = CQuery.Init(QueryFormat, Query, lFlags, m_strNamespace);
  696. if (SUCCEEDED(hr))
  697. {
  698. // Find the class name for the query
  699. bstr_t bstrClass (CQuery.GetQueryClassName(), false);
  700. if ((WCHAR *)bstrClass != NULL)
  701. {
  702. // Search for the class name in our map of providers, we know which
  703. // namespace we are when we get constructed.
  704. // pProvider doesn't get addref'ed, so doesn't need to be released.
  705. Provider *pProvider = SearchMapForProvider( bstrClass, m_strNamespace );
  706. if ( NULL != pProvider )
  707. {
  708. // Initialize the CQuery.m_keysonly variable. Note that we CAN'T do this as part
  709. // of Init, because we need the pProvider pointer. And we can do the init
  710. // down here, because we need the bstrClass that we get from Init. And we can't
  711. // do this as part of CQuery.KeysOnly because you can't get the IWbemClassObject
  712. // from there.
  713. IWbemClassObjectPtr IClass(pProvider->GetClassObjectInterface(pContext), false);
  714. if (IClass != NULL)
  715. {
  716. CQuery.Init2(IClass);
  717. // Impersonate connected user
  718. CWbemGlueImpersonation impersonate;
  719. if SUCCEEDED ( hr = impersonate.IsImpersonated () )
  720. {
  721. // Set up to call FlushAll
  722. AddFlushPtr(pProvider);
  723. WCHAR wszName[UNLEN + DNLEN + 1 + 1] = {0};
  724. WCHAR wszName2[UNLEN + DNLEN + 1 + 1] = {0}; // domain + \ + name + null
  725. DWORD dwLen = UNLEN + DNLEN + 1 + 1;
  726. GetUserNameEx(NameSamCompatible, wszName, &dwLen);
  727. // Everything is in place, run the query
  728. hr = pProvider->ExecuteQuery( pContext, CQuery, lFlags );
  729. dwLen = UNLEN + DNLEN + 1 + 1;
  730. GetUserNameEx(NameSamCompatible, wszName2, &dwLen);
  731. if (wcscmp(wszName, wszName2) != 0)
  732. {
  733. ASSERT_BREAK(IMPERSONATION_REVERTED);
  734. LogErrorMessage4(L"Warning! User name at exit (%s) != user name at entry (%s) for %s",
  735. wszName2, wszName, Query);
  736. }
  737. }
  738. }
  739. else
  740. {
  741. // we don't know WHY we couldn't get the interface,
  742. // generic error it is...
  743. hr = WBEM_E_FAILED;
  744. }
  745. }
  746. else
  747. {
  748. LogErrorMessage4(L"%s (%s:%s)", IDS_PROVIDERNOTFOUND, (LPCWSTR)m_strNamespace, (LPCWSTR)bstrClass);
  749. hr = WBEM_E_INVALID_CLASS;
  750. }
  751. }
  752. else
  753. {
  754. LogErrorMessage(IDS_INVALIDCLASSNAME);
  755. hr = WBEM_E_INVALID_CLASS;
  756. }
  757. }
  758. pStatusObject.Attach(pContext->GetStatusObject());
  759. }
  760. else
  761. {
  762. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  763. }
  764. if (IsVerboseLoggingEnabled())
  765. {
  766. if (SUCCEEDED(hr))
  767. LogMessage3(L"%s%s - Succeeded", IDS_EXECQUERY, Query);
  768. else
  769. LogMessage4(L"%s%s - FAILED (%x)", IDS_EXECQUERY, Query, hr);
  770. }
  771. }
  772. catch ( CFramework_Exception e_FR )
  773. {
  774. ASSERT_BREAK(FRAMEWORK_EXCEPTION);
  775. hr = WBEM_E_PROVIDER_FAILURE;
  776. }
  777. catch ( CHeap_Exception e_HE )
  778. {
  779. ASSERT_BREAK(MEMORY_EXHAUSTED);
  780. hr = WBEM_E_OUT_OF_MEMORY;
  781. }
  782. catch(CStructured_Exception e_SE)
  783. {
  784. ASSERT_BREAK(STRUCTURED_EXCEPTION);
  785. hr = WBEM_E_PROVIDER_FAILURE;
  786. }
  787. catch ( ... )
  788. {
  789. ASSERT_BREAK(UNSPECIFIED_EXCEPTION);
  790. hr = WBEM_E_PROVIDER_FAILURE;
  791. }
  792. // We must call SetStatus so CIMOM doesn't lose any threads.
  793. if ((hr != WBEM_E_INVALID_CLASS) && (hr != WBEM_E_UNSUPPORTED_PARAMETER))
  794. {
  795. #ifdef PROVIDER_INSTRUMENTATION
  796. stopWatch.Start(StopWatch::WinMgmtTimer);
  797. #endif
  798. pResponseHandler->SetStatus( 0, hr, NULL, pStatusObject);
  799. #ifdef PROVIDER_INSTRUMENTATION
  800. stopWatch.Start(StopWatch::FrameworkTimer);
  801. #endif
  802. hr = WBEM_S_NO_ERROR;
  803. }
  804. Release();
  805. #ifdef PROVIDER_INSTRUMENTATION
  806. stopWatch.Stop();
  807. stopWatch.LogResults();
  808. #endif
  809. return hr;
  810. }
  811. /////////////////////////////////////////////////////////////////////
  812. //
  813. // Function: CWbemProviderGlue::CreateInstanceEnumAsync
  814. //
  815. // Locates the provider for the specified class name and
  816. // calls its CreateInstanceEnum function.
  817. //
  818. // Inputs: const BSTR Class - Name of provider
  819. // long lFlags - Enumeration flags.
  820. // IWbemContext __RPC_FAR *pCtxt - Context pointer
  821. // IWbemObjectSink __RPC_FAR *pResponseHandler - Response
  822. // handler.
  823. //
  824. // Outputs: None.
  825. //
  826. // Returns: SCCODE - COM Status.
  827. //
  828. // Comments: None.
  829. //
  830. /////////////////////////////////////////////////////////////////////
  831. HRESULT CWbemProviderGlue::CreateInstanceEnumAsync(
  832. const BSTR a_bstrClass,
  833. long lFlags,
  834. IWbemContext __RPC_FAR *pCtx,
  835. IWbemObjectSink __RPC_FAR *pResponseHandler
  836. )
  837. {
  838. // make sure we don't disappear while running
  839. AddRef();
  840. CSetStructuredExceptionHandler t_ExceptionHandler;
  841. #ifdef PROVIDER_INSTRUMENTATION
  842. StopWatch stopWatch(CHString(IDS_CREATEINSTANCEENUM) + CHString(Class));
  843. stopWatch.Start(StopWatch::FrameworkTimer);
  844. #endif
  845. HRESULT hr = WBEM_E_INVALID_CLASS;
  846. IWbemClassObjectPtr pStatusObject;
  847. bool bSendStatus = true;
  848. try
  849. {
  850. if (IsVerboseLoggingEnabled())
  851. {
  852. LogMessage3(L"%s%s", IDS_CREATEINSTANCEENUM, a_bstrClass);
  853. }
  854. // Check for per-property gets
  855. CFrameworkQueryEx CQuery;
  856. hr = CQuery.Init(NULL, pCtx, a_bstrClass, m_strNamespace);
  857. // Note that we AREN'T calling Init2, which means if they specified "__RELPATH"
  858. // as their property, we won't expand that out to the key names. However, since
  859. // we are going to call ExecQuery, and it reprocesses the query and DOES call
  860. // Init2, this isn't an issue.
  861. // CQuery.Init2(pWbemClassObject);
  862. // If they are doing per-property gets, then turn this into a query.
  863. if (SUCCEEDED(hr))
  864. {
  865. if (CQuery.AllPropertiesAreRequired())
  866. {
  867. // Search for the class name in our map of providers, we know which
  868. // namespace we are when we get constructed.
  869. // pProvider doesn't get addref'ed, so no release necessary
  870. Provider *pProvider = SearchMapForProvider( a_bstrClass, m_strNamespace );
  871. if ( NULL != pProvider )
  872. {
  873. // Now create an External Method Context object and go to town
  874. ExternalMethodContextPtr pContext (new ExternalMethodContext( pResponseHandler, pCtx, this ), false);
  875. if ( NULL != pContext )
  876. {
  877. CWbemGlueImpersonation impersonate;
  878. if SUCCEEDED ( hr = impersonate.IsImpersonated () )
  879. {
  880. // Set up to call FlushAll
  881. AddFlushPtr(pProvider);
  882. WCHAR wszName[UNLEN + DNLEN + 1 + 1] = {0};
  883. WCHAR wszName2[UNLEN + DNLEN + 1 + 1] = {0}; // domain + \ + name + null
  884. DWORD dwLen = UNLEN + DNLEN + 1 + 1;
  885. GetUserNameEx(NameSamCompatible, wszName, &dwLen);
  886. #ifdef PROVIDER_INSTRUMENTATION
  887. pContext->pStopWatch = &stopWatch;
  888. #endif
  889. hr = pProvider->CreateInstanceEnum( pContext, lFlags );
  890. dwLen = UNLEN + DNLEN + 1 + 1;
  891. GetUserNameEx(NameSamCompatible, wszName2, &dwLen);
  892. if (wcscmp(wszName, wszName2) != 0)
  893. {
  894. ASSERT_BREAK(IMPERSONATION_REVERTED);
  895. LogErrorMessage4(L"Warning! User name at exit (%s) != user name at entry (%s) for %s",
  896. wszName2, wszName, a_bstrClass);
  897. }
  898. }
  899. pStatusObject.Attach(pContext->GetStatusObject());
  900. }
  901. else
  902. {
  903. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  904. }
  905. }
  906. else
  907. {
  908. LogErrorMessage4(L"%s (%s:%s)", IDS_PROVIDERNOTFOUND, (LPCWSTR)m_strNamespace, a_bstrClass);
  909. hr = WBEM_E_INVALID_CLASS;
  910. bSendStatus = false;
  911. }
  912. }
  913. else
  914. {
  915. bstr_t bstrtQuery = CQuery.GetQuery();
  916. hr =
  917. ExecQueryAsync(
  918. L"WQL",
  919. bstrtQuery,
  920. lFlags,
  921. pCtx,
  922. pResponseHandler);
  923. // Since execquery sent whatever status is necessary
  924. bSendStatus = false;
  925. }
  926. }
  927. if (IsVerboseLoggingEnabled())
  928. {
  929. if (SUCCEEDED(hr))
  930. LogMessage3(L"%s%s - Succeeded", IDS_CREATEINSTANCEENUM, a_bstrClass);
  931. else
  932. LogMessage4(L"%s%s - FAILED (%x)", IDS_CREATEINSTANCEENUM, a_bstrClass, hr);
  933. }
  934. }
  935. catch ( CFramework_Exception e_FR )
  936. {
  937. ASSERT_BREAK(FRAMEWORK_EXCEPTION);
  938. hr = WBEM_E_PROVIDER_FAILURE;
  939. }
  940. catch ( CHeap_Exception e_HE )
  941. {
  942. ASSERT_BREAK(MEMORY_EXHAUSTED);
  943. hr = WBEM_E_OUT_OF_MEMORY;
  944. }
  945. catch(CStructured_Exception e_SE)
  946. {
  947. ASSERT_BREAK(STRUCTURED_EXCEPTION);
  948. hr = WBEM_E_PROVIDER_FAILURE;
  949. }
  950. catch ( ... )
  951. {
  952. ASSERT_BREAK(UNSPECIFIED_EXCEPTION);
  953. hr = WBEM_E_PROVIDER_FAILURE;
  954. }
  955. if ((hr != WBEM_E_INVALID_CLASS) && (hr != WBEM_E_UNSUPPORTED_PARAMETER) && bSendStatus)
  956. {
  957. #ifdef PROVIDER_INSTRUMENTATION
  958. stopWatch.Start(StopWatch::WinMgmtTimer);
  959. #endif
  960. pResponseHandler->SetStatus( 0, hr, NULL, pStatusObject );
  961. #ifdef PROVIDER_INSTRUMENTATION
  962. stopWatch.Start(StopWatch::FrameworkTimer);
  963. #endif
  964. hr = WBEM_S_NO_ERROR;
  965. }
  966. Release();
  967. #ifdef PROVIDER_INSTRUMENTATION
  968. stopWatch.Stop();
  969. stopWatch.LogResults();
  970. #endif
  971. return hr;
  972. }
  973. /////////////////////////////////////////////////////////////////////
  974. //
  975. // Function: CWbemProviderGlue::GetObjectAsync
  976. //
  977. // Parses the supplied object path and hands the request off
  978. // to the appropriate provider.
  979. //
  980. // Inputs: const BSTR ObjPath - Object Path containing
  981. // keys to required object.
  982. // long lFlags - Get Object flags.
  983. // IWbemContext __RPC_FAR *pCtxt - Context pointer
  984. // IWbemObjectSink __RPC_FAR *pResponseHandler - Response
  985. // handler.
  986. //
  987. // Outputs: None.
  988. //
  989. // Returns: SCCODE - COM Status.
  990. //
  991. // Comments: None.
  992. //
  993. /////////////////////////////////////////////////////////////////////
  994. HRESULT CWbemProviderGlue::GetObjectAsync(
  995. const BSTR ObjectPath,
  996. long lFlags,
  997. IWbemContext __RPC_FAR *pCtx,
  998. IWbemObjectSink __RPC_FAR *pResponseHandler
  999. )
  1000. {
  1001. // make sure we don't disappear while running
  1002. AddRef();
  1003. CSetStructuredExceptionHandler t_ExceptionHandler;
  1004. #ifdef PROVIDER_INSTRUMENTATION
  1005. StopWatch stopWatch(CHString(IDS_GETOBJECTASYNC) + CHString(ObjectPath));
  1006. stopWatch.Start(StopWatch::FrameworkTimer);
  1007. #endif
  1008. HRESULT hr = WBEM_E_FAILED;
  1009. bool bLocalError = false;
  1010. IWbemClassObjectPtr pStatusObject;
  1011. ParsedObjectPath *pParsedPath = NULL;
  1012. CObjectPathParser objpathParser;
  1013. try
  1014. {
  1015. if (IsVerboseLoggingEnabled())
  1016. {
  1017. LogMessage3(L"%s%s", IDS_GETOBJECTASYNC, ObjectPath);
  1018. }
  1019. // Parse the object path passed to us by CIMOM
  1020. // ==========================================
  1021. int nStatus = objpathParser.Parse( ObjectPath, &pParsedPath );
  1022. if ( 0 == nStatus )
  1023. {
  1024. // Now try to find the provider based on the class name
  1025. // pProvider doesn't get addref'ed, so no release necessary
  1026. Provider *pProvider = SearchMapForProvider( pParsedPath->m_pClass, m_strNamespace );
  1027. // If we got a provider, let it handle itself like a grown-up provider
  1028. // should.
  1029. if ( NULL != pProvider )
  1030. {
  1031. // Now create an External Method Context object and go to town
  1032. ExternalMethodContextPtr pContext (new ExternalMethodContext( pResponseHandler, pCtx, this ), false);
  1033. if ( NULL != pContext )
  1034. {
  1035. #ifdef PROVIDER_INSTRUMENTATION
  1036. pContext->pStopWatch = &stopWatch;
  1037. #endif
  1038. CWbemGlueImpersonation impersonate;
  1039. if SUCCEEDED ( hr = impersonate.IsImpersonated () )
  1040. {
  1041. // Set up to call FlushAll
  1042. AddFlushPtr(pProvider);
  1043. WCHAR wszName[UNLEN + DNLEN + 1 + 1] = {0};
  1044. WCHAR wszName2[UNLEN + DNLEN + 1 + 1] = {0}; // domain + \ + name + null
  1045. DWORD dwLen = UNLEN + DNLEN + 1 + 1;
  1046. GetUserNameEx(NameSamCompatible, wszName, &dwLen);
  1047. hr = pProvider->GetObject( pParsedPath, pContext, lFlags );
  1048. dwLen = UNLEN + DNLEN + 1 + 1;
  1049. GetUserNameEx(NameSamCompatible, wszName2, &dwLen);
  1050. if (wcscmp(wszName, wszName2) != 0)
  1051. {
  1052. ASSERT_BREAK(IMPERSONATION_REVERTED);
  1053. LogErrorMessage4(L"Warning! User name at exit (%s) != user name at entry (%s) for %s",
  1054. wszName2, wszName, ObjectPath);
  1055. }
  1056. }
  1057. pStatusObject.Attach(pContext->GetStatusObject());
  1058. }
  1059. else
  1060. {
  1061. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  1062. }
  1063. }
  1064. else
  1065. {
  1066. LogErrorMessage4(L"%s (%s:%s)", IDS_PROVIDERNOTFOUND, (LPCWSTR)m_strNamespace, pParsedPath->m_pClass);
  1067. hr = WBEM_E_INVALID_CLASS;
  1068. bLocalError = true;
  1069. }
  1070. }
  1071. if (IsVerboseLoggingEnabled())
  1072. {
  1073. if (SUCCEEDED(hr))
  1074. LogMessage3(L"%s%s - Succeeded", IDS_GETOBJECTASYNC, ObjectPath);
  1075. else
  1076. LogMessage4(L"%s%s - FAILED (%x)", IDS_GETOBJECTASYNC, ObjectPath, hr);
  1077. }
  1078. }
  1079. catch ( CFramework_Exception e_FR )
  1080. {
  1081. ASSERT_BREAK(FRAMEWORK_EXCEPTION);
  1082. hr = WBEM_E_PROVIDER_FAILURE;
  1083. }
  1084. catch ( CHeap_Exception e_HE )
  1085. {
  1086. ASSERT_BREAK(MEMORY_EXHAUSTED);
  1087. hr = WBEM_E_OUT_OF_MEMORY;
  1088. }
  1089. catch(CStructured_Exception e_SE)
  1090. {
  1091. ASSERT_BREAK(STRUCTURED_EXCEPTION);
  1092. hr = WBEM_E_PROVIDER_FAILURE;
  1093. }
  1094. catch ( ... )
  1095. {
  1096. ASSERT_BREAK(UNSPECIFIED_EXCEPTION);
  1097. hr = WBEM_E_PROVIDER_FAILURE;
  1098. }
  1099. if ((hr != WBEM_E_INVALID_CLASS) && (hr != WBEM_E_UNSUPPORTED_PARAMETER) && !bLocalError)
  1100. {
  1101. #ifdef PROVIDER_INSTRUMENTATION
  1102. stopWatch.Start(StopWatch::WinMgmtTimer);
  1103. #endif
  1104. pResponseHandler->SetStatus( 0, hr, NULL, pStatusObject );
  1105. #ifdef PROVIDER_INSTRUMENTATION
  1106. stopWatch.Start(StopWatch::FrameworkTimer);
  1107. #endif
  1108. hr = WBEM_S_NO_ERROR;
  1109. }
  1110. // Clean up the Parsed Path
  1111. if (pParsedPath)
  1112. {
  1113. objpathParser.Free( pParsedPath );
  1114. }
  1115. Release();
  1116. #ifdef PROVIDER_INSTRUMENTATION
  1117. stopWatch.Stop();
  1118. stopWatch.LogResults();
  1119. #endif
  1120. return hr;
  1121. }
  1122. /////////////////////////////////////////////////////////////////////
  1123. //
  1124. // Function: CWbemProviderGlue::PutInstanceAsync
  1125. //
  1126. // Locates the provider for the specified class name and
  1127. // calls its CreateInstanceEnum function.
  1128. //
  1129. // Inputs: IWbemClassObject __RPC_FAR *pInst - Instance whose
  1130. // values to use.
  1131. // long lFlags - PutInstance flags.
  1132. // IWbemContext __RPC_FAR *pCtxt - Context pointer
  1133. // IWbemObjectSink __RPC_FAR *pResponseHandler - Response
  1134. // handler.
  1135. //
  1136. // Outputs: None.
  1137. //
  1138. // Returns: SCCODE - COM Status.
  1139. //
  1140. // Comments: None.
  1141. //
  1142. /////////////////////////////////////////////////////////////////////
  1143. HRESULT CWbemProviderGlue::PutInstanceAsync(
  1144. IWbemClassObject __RPC_FAR *pInst,
  1145. long lFlags,
  1146. IWbemContext __RPC_FAR *pCtx,
  1147. IWbemObjectSink __RPC_FAR *pResponseHandler
  1148. )
  1149. {
  1150. // make sure we don't disappear while running
  1151. AddRef();
  1152. CSetStructuredExceptionHandler t_ExceptionHandler;
  1153. HRESULT hr = WBEM_E_INVALID_CLASS;
  1154. variant_t vClass;
  1155. bool bLocalError = false;
  1156. IWbemClassObjectPtr pStatusObject;
  1157. try
  1158. {
  1159. // Set up to get the class name of the instance being passed to us
  1160. // ask the framework if it has this class registered for support
  1161. // ===============================================================
  1162. // Get the class name
  1163. pInst->Get( IDS_CLASS, 0, &vClass, NULL, NULL );
  1164. if (IsVerboseLoggingEnabled())
  1165. {
  1166. LogMessage3(L"%s%s", IDS_PUTINSTANCEASYNC, vClass.bstrVal);
  1167. }
  1168. // pProvider doesn't get addref'ed, so no release necessary
  1169. Provider *pProvider = SearchMapForProvider( vClass.bstrVal, m_strNamespace );
  1170. // If we got a provider, let it handle itself like a grown-up provider
  1171. // should.
  1172. if ( NULL != pProvider )
  1173. {
  1174. // Now create an External Method Context object and go to town
  1175. ExternalMethodContextPtr pContext (new ExternalMethodContext( pResponseHandler, pCtx, this ), false);
  1176. if ( NULL != pContext )
  1177. {
  1178. IWbemClassObjectPtr pInstPostProcess;
  1179. if (SUCCEEDED(hr = PreProcessPutInstanceParms(pInst, &pInstPostProcess, pCtx)))
  1180. {
  1181. CWbemGlueImpersonation impersonate;
  1182. if SUCCEEDED ( hr = impersonate.IsImpersonated () )
  1183. {
  1184. // Set up to call FlushAll
  1185. AddFlushPtr(pProvider);
  1186. WCHAR wszName[UNLEN + DNLEN + 1 + 1] = {0};
  1187. WCHAR wszName2[UNLEN + DNLEN + 1 + 1] = {0}; // domain + \ + name + null
  1188. DWORD dwLen = UNLEN + DNLEN + 1 + 1;
  1189. GetUserNameEx(NameSamCompatible, wszName, &dwLen);
  1190. hr = pProvider->PutInstance( pInstPostProcess, lFlags, pContext );
  1191. dwLen = UNLEN + DNLEN + 1 + 1;
  1192. GetUserNameEx(NameSamCompatible, wszName2, &dwLen);
  1193. if (wcscmp(wszName, wszName2) != 0)
  1194. {
  1195. ASSERT_BREAK(IMPERSONATION_REVERTED);
  1196. LogErrorMessage4(L"Warning! User name at exit (%s) != user name at entry (%s) for %s",
  1197. wszName2, wszName, vClass.bstrVal);
  1198. }
  1199. }
  1200. }
  1201. pStatusObject.Attach(pContext->GetStatusObject());
  1202. }
  1203. else
  1204. {
  1205. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  1206. }
  1207. }
  1208. else
  1209. {
  1210. LogErrorMessage4(L"%s (%s:%s)", IDS_PROVIDERNOTFOUND, (LPCWSTR)m_strNamespace, vClass.bstrVal);
  1211. hr = WBEM_E_INVALID_CLASS;
  1212. bLocalError = true;
  1213. }
  1214. if (IsVerboseLoggingEnabled())
  1215. {
  1216. if (SUCCEEDED(hr))
  1217. LogMessage3(L"%s%s - Succeeded", IDS_PUTINSTANCEASYNC, vClass.bstrVal);
  1218. else
  1219. LogMessage4(L"%s%s - FAILED (%x)", IDS_PUTINSTANCEASYNC, vClass.bstrVal, hr);
  1220. }
  1221. }
  1222. catch ( CFramework_Exception e_FR )
  1223. {
  1224. ASSERT_BREAK(FRAMEWORK_EXCEPTION);
  1225. hr = WBEM_E_PROVIDER_FAILURE;
  1226. }
  1227. catch ( CHeap_Exception e_HE )
  1228. {
  1229. ASSERT_BREAK(MEMORY_EXHAUSTED);
  1230. hr = WBEM_E_OUT_OF_MEMORY;
  1231. }
  1232. catch(CStructured_Exception e_SE)
  1233. {
  1234. ASSERT_BREAK(STRUCTURED_EXCEPTION);
  1235. hr = WBEM_E_PROVIDER_FAILURE;
  1236. }
  1237. catch ( ... )
  1238. {
  1239. ASSERT_BREAK(UNSPECIFIED_EXCEPTION);
  1240. hr = WBEM_E_PROVIDER_FAILURE;
  1241. }
  1242. if ((hr != WBEM_E_INVALID_CLASS) && (hr != WBEM_E_UNSUPPORTED_PARAMETER) && !bLocalError)
  1243. {
  1244. pResponseHandler->SetStatus( 0, hr, NULL, pStatusObject );
  1245. hr = WBEM_S_NO_ERROR;
  1246. }
  1247. Release();
  1248. return hr;
  1249. }
  1250. /////////////////////////////////////////////////////////////////////
  1251. //
  1252. // Function: CWbemProviderGlue::PreProcessPutInstanceParms()
  1253. //
  1254. // IF __PUT_EXT_PROPERTIES is specified, will parse out the intended properties
  1255. // and set to NULL those props that are not explicitly being put.
  1256. //
  1257. // Inputs: [IN] IWbemClassObject __RPC_FAR *pInstIn - Instance whose values to use.
  1258. // [OUT] IWbemClassObject __RPC_FAR **pInstOut - processed instance
  1259. // IWbemContext __RPC_FAR *pCtxt - Context pointer
  1260. //
  1261. // Outputs: None.
  1262. //
  1263. // Returns: WBEM_S_NO_ERROR if the only extension specified is __PUT_EXT_PROPERTIES
  1264. // or if no extensions are specified
  1265. // WBEM_E_UNSUPPORTED_PUT_EXTENSION if any other flag is set.
  1266. // WBEM_E_SEVERE_SCREWUP if some other darn thing happened.
  1267. //
  1268. // Comments: You may get a different IWbemObject out than you put in
  1269. // it's your responsibility to release it.
  1270. // On error - pInstOut is undefined.
  1271. //
  1272. /////////////////////////////////////////////////////////////////////
  1273. HRESULT CWbemProviderGlue::PreProcessPutInstanceParms(
  1274. IWbemClassObject __RPC_FAR *pInstIn,
  1275. IWbemClassObject __RPC_FAR **pInstOut,
  1276. IWbemContext __RPC_FAR *pCtx
  1277. )
  1278. {
  1279. HRESULT hr = WBEM_S_NO_ERROR;
  1280. // Variant_t handles the VariantInit/VariantClear
  1281. variant_t vValue;
  1282. if (
  1283. pCtx != NULL &&
  1284. SUCCEEDED(hr = pCtx->GetValue( L"__PUT_EXTENSIONS", 0, &vValue)) &&
  1285. V_VT(&vValue) == VT_BOOL &&
  1286. V_BOOL(&vValue) == VARIANT_TRUE
  1287. )
  1288. {
  1289. // easy checks first, are there unsupported parms?
  1290. vValue.Clear();
  1291. if (SUCCEEDED(hr = pCtx->GetValue( L"__PUT_EXT_STRICT_NULLS", 0, &vValue))
  1292. && (V_VT(&vValue) == VT_BOOL)
  1293. && (V_BOOL(&vValue) == VARIANT_TRUE))
  1294. hr = WBEM_E_UNSUPPORTED_PUT_EXTENSION;
  1295. else
  1296. {
  1297. vValue.Clear();
  1298. if (SUCCEEDED(hr = pCtx->GetValue( L"__PUT_EXT_ATOMIC", 0, &vValue))
  1299. && (V_VT(&vValue) == VT_BOOL)
  1300. && (V_BOOL(&vValue) == VARIANT_TRUE))
  1301. hr = WBEM_E_UNSUPPORTED_PUT_EXTENSION;
  1302. }
  1303. vValue.Clear();
  1304. if ((SUCCEEDED(hr) || (hr != WBEM_E_UNSUPPORTED_PUT_EXTENSION))
  1305. && SUCCEEDED(hr = pCtx->GetValue( L"__PUT_EXT_PROPERTIES", 0, &vValue)))
  1306. {
  1307. if (V_VT(&vValue) == (VT_BSTR|VT_ARRAY))
  1308. hr = NullOutUnsetProperties(pInstIn, pInstOut, vValue);
  1309. else
  1310. hr = WBEM_E_INVALID_PARAMETER;
  1311. }
  1312. else if (hr == WBEM_E_NOT_FOUND)
  1313. {
  1314. // well, if we've never heard of it, it MUST be wrong...
  1315. hr = WBEM_E_UNSUPPORTED_PUT_EXTENSION;
  1316. }
  1317. }
  1318. else if (hr == WBEM_E_NOT_FOUND)
  1319. {
  1320. // no extensions - no problems.
  1321. // out interface is same as in interface
  1322. hr = WBEM_S_NO_ERROR;
  1323. *pInstOut = pInstIn;
  1324. (*pInstOut)->AddRef();
  1325. }
  1326. return hr;
  1327. }
  1328. /////////////////////////////////////////////////////////////////////
  1329. //
  1330. // Function: CWbemProviderGlue::NullOutUnsetProperties
  1331. //
  1332. // returns a copy of the input class, any properties whose names are listed
  1333. // in the variant are set to NULL in the output class
  1334. //
  1335. //
  1336. // Inputs: IWbemClassObject __RPC_FAR *pInst - Instance whose
  1337. // values to NULL
  1338. // VARIANT contains names to not NULL out.
  1339. //
  1340. // Outputs: None.
  1341. //
  1342. // Returns: the ubiquitous HRESULT
  1343. //
  1344. // Comments: Assumes you've done your homework and the Variant
  1345. // is a BSTR Array containing property names.
  1346. //
  1347. /////////////////////////////////////////////////////////////////////
  1348. HRESULT CWbemProviderGlue::NullOutUnsetProperties(
  1349. IWbemClassObject __RPC_FAR *pInstIn,
  1350. IWbemClassObject __RPC_FAR **pInstOut,
  1351. const VARIANT& vValue
  1352. )
  1353. {
  1354. HRESULT hRes = WBEM_S_NO_ERROR;
  1355. // get ourselves a copy to work with
  1356. CInstancePtr pInstance;
  1357. // Variant_t handles the VariantInit/VariantClear
  1358. variant_t vName;
  1359. variant_t vNameSpace;
  1360. hRes = pInstIn->Get(IDS_CLASS, 0, &vName, NULL, NULL);
  1361. if (SUCCEEDED(hRes))
  1362. {
  1363. hRes = pInstIn->Get(L"__NAMESPACE", 0, &vNameSpace, NULL, NULL);
  1364. }
  1365. if (SUCCEEDED(hRes) && SUCCEEDED( hRes = GetEmptyInstance(vName.bstrVal, &pInstance, vNameSpace.bstrVal)))
  1366. {
  1367. // and off we go...
  1368. SAFEARRAY *pNames = vValue.parray;
  1369. long nBiggestName;
  1370. if (SUCCEEDED(hRes = SafeArrayGetUBound(pNames, 1, &nBiggestName)))
  1371. {
  1372. BSTR t_bstrName = NULL ;
  1373. *pInstOut = pInstance->GetClassObjectInterface();
  1374. variant_t value;
  1375. // wander through the names, for every one we find
  1376. // copy the property value to the out pointer
  1377. for (long i = 0; i <= nBiggestName; i++)
  1378. {
  1379. SafeArrayGetElement(pNames, &i, t_bstrName ) ;
  1380. try
  1381. {
  1382. pInstIn->Get( t_bstrName, 0, &value, NULL, NULL);
  1383. (*pInstOut)->Put( t_bstrName, 0, &value, 0);
  1384. }
  1385. catch( ... )
  1386. {
  1387. SysFreeString( t_bstrName ) ;
  1388. throw ;
  1389. }
  1390. SysFreeString( t_bstrName ) ;
  1391. }
  1392. // and, oh what the heck - let's copy the keys, too...
  1393. SAFEARRAY *pKeyNames = NULL;
  1394. if (SUCCEEDED(hRes = pInstIn->GetNames(NULL, WBEM_FLAG_KEYS_ONLY, NULL, &pKeyNames)))
  1395. {
  1396. try
  1397. {
  1398. SafeArrayGetUBound(pKeyNames, 1, &nBiggestName);
  1399. for (i = 0; i <= nBiggestName; i++)
  1400. {
  1401. try
  1402. {
  1403. SafeArrayGetElement( pKeyNames, &i, t_bstrName );
  1404. pInstIn->Get( t_bstrName, 0, &value, NULL, NULL );
  1405. (*pInstOut)->Put( t_bstrName, 0, &value, 0 );
  1406. }
  1407. catch( ... )
  1408. {
  1409. SysFreeString( t_bstrName ) ;
  1410. throw ;
  1411. }
  1412. SysFreeString( t_bstrName ) ;
  1413. }
  1414. }
  1415. catch (...)
  1416. {
  1417. SafeArrayDestroy(pKeyNames);
  1418. throw ;
  1419. }
  1420. SafeArrayDestroy(pKeyNames);
  1421. }
  1422. }
  1423. else
  1424. {
  1425. // failed to get array upper bound!
  1426. hRes = WBEM_E_FAILED;
  1427. }
  1428. }
  1429. return hRes;
  1430. }
  1431. /////////////////////////////////////////////////////////////////////
  1432. //
  1433. // Function: CWbemProviderGlue::DeleteInstanceAsync
  1434. //
  1435. // Locates the provider for the specified class name and
  1436. // calls its DeleteInstance function.
  1437. //
  1438. // Inputs: IWbemClassObject __RPC_FAR *pInst - Instance whose
  1439. // values to use.
  1440. // long lFlags - PutInstance flags.
  1441. // IWbemContext __RPC_FAR *pCtxt - Context pointer
  1442. // IWbemObjectSink __RPC_FAR *pResponseHandler - Response
  1443. // handler.
  1444. //
  1445. // Outputs: None.
  1446. //
  1447. // Returns: SCCODE - COM Status.
  1448. //
  1449. // Comments: None.
  1450. //
  1451. /////////////////////////////////////////////////////////////////////
  1452. HRESULT CWbemProviderGlue::DeleteInstanceAsync(
  1453. const BSTR ObjectPath,
  1454. long lFlags,
  1455. IWbemContext __RPC_FAR *pCtx,
  1456. IWbemObjectSink __RPC_FAR *pResponseHandler
  1457. )
  1458. {
  1459. // make sure we don't disappear while running
  1460. AddRef();
  1461. CSetStructuredExceptionHandler t_ExceptionHandler;
  1462. HRESULT hr = WBEM_E_FAILED;
  1463. bool bLocalError = false;
  1464. IWbemClassObjectPtr pStatusObject;
  1465. ParsedObjectPath *pParsedPath = NULL;
  1466. CObjectPathParser objpathParser;
  1467. try
  1468. {
  1469. if (IsVerboseLoggingEnabled())
  1470. {
  1471. LogMessage3(L"%s%s", IDS_DELETEINSTANCEASYNC, ObjectPath);
  1472. }
  1473. // Parse the object path passed to us by CIMOM
  1474. // ==========================================
  1475. int nStatus = objpathParser.Parse( ObjectPath, &pParsedPath );
  1476. if ( 0 == nStatus )
  1477. {
  1478. // Now try to find the provider based on the class name
  1479. // pProvider doesn't get addref'ed, so no release necessary
  1480. Provider *pProvider = SearchMapForProvider( pParsedPath->m_pClass, m_strNamespace );
  1481. // If we got a provider, let it handle itself like a grown-up provider
  1482. // should.
  1483. if ( NULL != pProvider )
  1484. {
  1485. // Now create an External Method Context object and go to town
  1486. ExternalMethodContextPtr pContext (new ExternalMethodContext( pResponseHandler, pCtx, this ), false);
  1487. if ( NULL != pContext )
  1488. {
  1489. CWbemGlueImpersonation impersonate;
  1490. if SUCCEEDED ( hr = impersonate.IsImpersonated () )
  1491. {
  1492. // Set up to call FlushAll
  1493. AddFlushPtr(pProvider);
  1494. WCHAR wszName[UNLEN + DNLEN + 1 + 1] = {0};
  1495. WCHAR wszName2[UNLEN + DNLEN + 1 + 1] = {0}; // domain + \ + name + null
  1496. DWORD dwLen = UNLEN + DNLEN + 1 + 1;
  1497. GetUserNameEx(NameSamCompatible, wszName, &dwLen);
  1498. hr = pProvider->DeleteInstance( pParsedPath, lFlags, pContext );
  1499. dwLen = UNLEN + DNLEN + 1 + 1;
  1500. GetUserNameEx(NameSamCompatible, wszName2, &dwLen);
  1501. if (wcscmp(wszName, wszName2) != 0)
  1502. {
  1503. ASSERT_BREAK(IMPERSONATION_REVERTED);
  1504. LogErrorMessage4(L"Warning! User name at exit (%s) != user name at entry (%s) for %s",
  1505. wszName2, wszName, ObjectPath);
  1506. }
  1507. }
  1508. pStatusObject.Attach(pContext->GetStatusObject());
  1509. }
  1510. else
  1511. {
  1512. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  1513. }
  1514. }
  1515. else
  1516. {
  1517. hr = WBEM_E_INVALID_CLASS;
  1518. LogErrorMessage4(L"%s (%s:%s)", IDS_PROVIDERNOTFOUND, (LPCWSTR)m_strNamespace, pParsedPath->m_pClass);
  1519. bLocalError = true;
  1520. }
  1521. }
  1522. else
  1523. {
  1524. LogErrorMessage3(L"%s (%s)", IDS_COULDNOTPARSE, ObjectPath);
  1525. bLocalError = true;
  1526. }
  1527. if (IsVerboseLoggingEnabled())
  1528. {
  1529. if (SUCCEEDED(hr))
  1530. LogMessage3(L"%s%s - Succeeded", IDS_DELETEINSTANCEASYNC, ObjectPath);
  1531. else
  1532. LogMessage4(L"%s%s - FAILED (%x)", IDS_DELETEINSTANCEASYNC, ObjectPath, hr);
  1533. }
  1534. }
  1535. catch ( CFramework_Exception e_FR )
  1536. {
  1537. ASSERT_BREAK(FRAMEWORK_EXCEPTION);
  1538. hr = WBEM_E_PROVIDER_FAILURE;
  1539. }
  1540. catch ( CHeap_Exception e_HE )
  1541. {
  1542. ASSERT_BREAK(MEMORY_EXHAUSTED);
  1543. hr = WBEM_E_OUT_OF_MEMORY;
  1544. }
  1545. catch(CStructured_Exception e_SE)
  1546. {
  1547. ASSERT_BREAK(STRUCTURED_EXCEPTION);
  1548. hr = WBEM_E_PROVIDER_FAILURE;
  1549. }
  1550. catch ( ... )
  1551. {
  1552. ASSERT_BREAK(UNSPECIFIED_EXCEPTION);
  1553. hr = WBEM_E_PROVIDER_FAILURE;
  1554. }
  1555. if ((hr != WBEM_E_INVALID_CLASS) && (hr != WBEM_E_UNSUPPORTED_PARAMETER) && !bLocalError)
  1556. {
  1557. pResponseHandler->SetStatus( 0, hr, NULL, pStatusObject);
  1558. hr = WBEM_S_NO_ERROR;
  1559. }
  1560. // Clean up the Parsed Path
  1561. if (pParsedPath)
  1562. {
  1563. objpathParser.Free( pParsedPath );
  1564. }
  1565. Release();
  1566. return hr;
  1567. }
  1568. /////////////////////////////////////////////////////////////////////
  1569. //
  1570. // Function: CWbemProviderGlue::ExecMethodAsync
  1571. //
  1572. // Locates the provider for the specified class name and
  1573. // calls its ExecMethod function.
  1574. //
  1575. // Inputs:
  1576. // const BSTR ObjectPath, - Object path on which to execute the method
  1577. // const BSTR MethodName, - Name of the method to execute
  1578. // long lFlags, - Any flags
  1579. // IWbemContext __RPC_FAR *pCtx,
  1580. // IWbemClassObject __RPC_FAR *pInParams, - Pointer to IWbemClassObject
  1581. // that contains parms
  1582. // IWbemObjectSink __RPC_FAR *pResponseHandler)
  1583. //
  1584. // Outputs: None.
  1585. //
  1586. // Returns: SCCODE - COM Status.
  1587. //
  1588. // Comments: None.
  1589. //
  1590. /////////////////////////////////////////////////////////////////////
  1591. HRESULT CWbemProviderGlue::ExecMethodAsync(
  1592. const BSTR ObjectPath,
  1593. const BSTR MethodName,
  1594. long lFlags,
  1595. IWbemContext __RPC_FAR *pCtx,
  1596. IWbemClassObject __RPC_FAR *pInParams,
  1597. IWbemObjectSink __RPC_FAR *pResponseHandler
  1598. )
  1599. {
  1600. // make sure we don't disappear while running
  1601. AddRef();
  1602. CSetStructuredExceptionHandler t_ExceptionHandler;
  1603. #ifdef PROVIDER_INSTRUMENTATION
  1604. StopWatch stopWatch(CHString(IDS_EXECMETHODASYNC) + CHString(ObjectPath) + CHString(MethodName));
  1605. stopWatch.Start(StopWatch::FrameworkTimer);
  1606. #endif
  1607. HRESULT hr = WBEM_E_FAILED;
  1608. bool bLocalError = false;
  1609. IWbemClassObjectPtr pStatusObject;
  1610. ParsedObjectPath *pParsedPath = NULL;
  1611. CObjectPathParser objpathParser;
  1612. try
  1613. {
  1614. if (IsVerboseLoggingEnabled())
  1615. {
  1616. LogMessage4(L"%s%s.%s", IDS_EXECMETHODASYNC, ObjectPath, MethodName);
  1617. }
  1618. // Parse the object path passed to us by CIMOM
  1619. // ==========================================
  1620. int nStatus = objpathParser.Parse( ObjectPath, &pParsedPath );
  1621. if ( 0 == nStatus )
  1622. {
  1623. // Now try to find the provider based on the class name
  1624. // pProvider doesn't get addref'ed, so no release necessary
  1625. Provider *pProvider = SearchMapForProvider( pParsedPath->m_pClass, m_strNamespace );
  1626. // If we got a provider, let it handle itself like a grown-up provider
  1627. // should.
  1628. if ( NULL != pProvider )
  1629. {
  1630. IWbemClassObjectPtr pOutClass;
  1631. IWbemClassObjectPtr pOutParams;
  1632. CInstancePtr COutParam;
  1633. CInstancePtr CInParam;
  1634. hr = WBEM_S_NO_ERROR;
  1635. // Now create an External Method Context object and go to town
  1636. ExternalMethodContextPtr pContext (new ExternalMethodContext( pResponseHandler, pCtx, this ), false);
  1637. #ifdef PROVIDER_INSTRUMENTATION
  1638. pContext->pStopWatch = &stopWatch;
  1639. #endif
  1640. // Check for out of memory
  1641. if (NULL == pContext)
  1642. {
  1643. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  1644. }
  1645. // add check to ensure that we do not call a static method
  1646. // on an instance of a class.
  1647. if (SUCCEEDED(hr) && pParsedPath->IsInstance())
  1648. {
  1649. IWbemClassObjectPtr pObj(pProvider->GetClassObjectInterface(pContext), false);
  1650. if (pObj)
  1651. {
  1652. IWbemQualifierSetPtr pSet;
  1653. #ifdef PROVIDER_INSTRUMENTATION
  1654. stopWatch.Start(StopWatch::WinMgmtTimer);
  1655. #endif
  1656. if (SUCCEEDED(pObj->GetMethodQualifierSet(MethodName, &pSet)))
  1657. {
  1658. // disallow an instance to invoke a static method
  1659. #ifdef PROVIDER_INSTRUMENTATION
  1660. stopWatch.Start(StopWatch::WinMgmtTimer);
  1661. #endif
  1662. if (SUCCEEDED(pSet->Get( IDS_Static, 0, NULL, NULL)))
  1663. hr = WBEM_E_INVALID_METHOD;
  1664. #ifdef PROVIDER_INSTRUMENTATION
  1665. stopWatch.Start(StopWatch::FrameworkTimer);
  1666. #endif
  1667. }
  1668. }
  1669. }
  1670. // If there are in params, convert them to a cinstance.
  1671. if (SUCCEEDED(hr) && (NULL != pInParams) )
  1672. {
  1673. CInParam.Attach(new CInstance(pInParams, pContext));
  1674. if (NULL == CInParam)
  1675. {
  1676. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  1677. }
  1678. }
  1679. // Get the output class for the method
  1680. if (SUCCEEDED(hr))
  1681. {
  1682. IWbemClassObjectPtr pObj(pProvider->GetClassObjectInterface(pContext), false);
  1683. if (pObj != NULL)
  1684. {
  1685. #ifdef PROVIDER_INSTRUMENTATION
  1686. stopWatch.Start(StopWatch::WinMgmtTimer);
  1687. #endif
  1688. hr = pObj->GetMethod(MethodName, 0, NULL, &pOutClass);
  1689. #ifdef PROVIDER_INSTRUMENTATION
  1690. stopWatch.Start(StopWatch::FrameworkTimer);
  1691. #endif
  1692. }
  1693. else
  1694. {
  1695. hr = WBEM_E_FAILED;
  1696. }
  1697. }
  1698. // If there is no output class, pOutClass is null (by design). So, if there was no error
  1699. // and we got an pOutClass, get an instance and wrap it in a CInstance
  1700. if (SUCCEEDED(hr) && (pOutClass != NULL))
  1701. {
  1702. #ifdef PROVIDER_INSTRUMENTATION
  1703. stopWatch.Start(StopWatch::WinMgmtTimer);
  1704. #endif
  1705. hr = pOutClass->SpawnInstance(0, &pOutParams);
  1706. #ifdef PROVIDER_INSTRUMENTATION
  1707. stopWatch.Start(StopWatch::FrameworkTimer);
  1708. #endif
  1709. if (SUCCEEDED(hr))
  1710. {
  1711. COutParam.Attach(new CInstance(pOutParams, pContext));
  1712. // Out of memory
  1713. if (NULL == COutParam)
  1714. {
  1715. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  1716. }
  1717. }
  1718. }
  1719. if ( SUCCEEDED(hr) )
  1720. {
  1721. CWbemGlueImpersonation impersonate;
  1722. if SUCCEEDED ( hr = impersonate.IsImpersonated () )
  1723. {
  1724. // Set up to call FlushAll
  1725. AddFlushPtr(pProvider);
  1726. WCHAR wszName[UNLEN + DNLEN + 1 + 1] = {0};
  1727. WCHAR wszName2[UNLEN + DNLEN + 1 + 1] = {0}; // domain + \ + name + null
  1728. DWORD dwLen = UNLEN + DNLEN + 1 + 1;
  1729. GetUserNameEx(NameSamCompatible, wszName, &dwLen);
  1730. hr = pProvider->ExecMethod( pParsedPath, MethodName, lFlags, CInParam, COutParam, pContext );
  1731. dwLen = UNLEN + DNLEN + 1 + 1;
  1732. GetUserNameEx(NameSamCompatible, wszName2, &dwLen);
  1733. if (wcscmp(wszName, wszName2) != 0)
  1734. {
  1735. ASSERT_BREAK(IMPERSONATION_REVERTED);
  1736. LogErrorMessage5(L"Warning! User name at exit (%s) != user name at entry (%s) for %s.%s",
  1737. wszName2, wszName, ObjectPath, MethodName);
  1738. }
  1739. }
  1740. }
  1741. // If there is an output object
  1742. if (COutParam != NULL)
  1743. {
  1744. // Only send back an output object if the method succeeded
  1745. if (SUCCEEDED(hr))
  1746. {
  1747. // Send the object back
  1748. IWbemClassObjectPtr pObj(COutParam->GetClassObjectInterface(), false);
  1749. IWbemClassObject *pObj2 = (IWbemClassObject *)pObj;
  1750. #ifdef PROVIDER_INSTRUMENTATION
  1751. stopWatch.Start(StopWatch::WinMgmtTimer);
  1752. #endif
  1753. pResponseHandler->Indicate( 1, &pObj2);
  1754. #ifdef PROVIDER_INSTRUMENTATION
  1755. stopWatch.Start(StopWatch::FrameworkTimer);
  1756. #endif
  1757. }
  1758. }
  1759. pStatusObject.Attach(pContext->GetStatusObject());
  1760. }
  1761. else
  1762. {
  1763. LogErrorMessage3(L"%s (%s)", IDS_PROVIDERNOTFOUND, pParsedPath->m_pClass);
  1764. hr = WBEM_E_INVALID_CLASS;
  1765. bLocalError = true;
  1766. }
  1767. }
  1768. else
  1769. {
  1770. LogErrorMessage3(L"%s (%s)", IDS_COULDNOTPARSE, ObjectPath);
  1771. bLocalError = true;
  1772. }
  1773. if (IsVerboseLoggingEnabled())
  1774. {
  1775. if (SUCCEEDED(hr))
  1776. LogMessage4(L"%s%s.%s - Succeeded", IDS_EXECMETHODASYNC, ObjectPath, MethodName);
  1777. else
  1778. LogMessage5(L"%s%s.%s - FAILED (%x)", IDS_EXECMETHODASYNC, ObjectPath, MethodName, hr);
  1779. }
  1780. }
  1781. catch ( CFramework_Exception e_FR )
  1782. {
  1783. ASSERT_BREAK(FRAMEWORK_EXCEPTION);
  1784. hr = WBEM_E_PROVIDER_FAILURE;
  1785. }
  1786. catch ( CHeap_Exception e_HE )
  1787. {
  1788. ASSERT_BREAK(MEMORY_EXHAUSTED);
  1789. hr = WBEM_E_OUT_OF_MEMORY;
  1790. }
  1791. catch(CStructured_Exception e_SE)
  1792. {
  1793. ASSERT_BREAK(STRUCTURED_EXCEPTION);
  1794. hr = WBEM_E_PROVIDER_FAILURE;
  1795. }
  1796. catch ( ... )
  1797. {
  1798. ASSERT_BREAK(UNSPECIFIED_EXCEPTION);
  1799. hr = WBEM_E_PROVIDER_FAILURE;
  1800. }
  1801. if ((hr != WBEM_E_INVALID_CLASS) && (hr != WBEM_E_UNSUPPORTED_PARAMETER) && !bLocalError)
  1802. {
  1803. #ifdef PROVIDER_INSTRUMENTATION
  1804. stopWatch.Start(StopWatch::WinMgmtTimer);
  1805. #endif
  1806. pResponseHandler->SetStatus( 0, hr, NULL, pStatusObject );
  1807. #ifdef PROVIDER_INSTRUMENTATION
  1808. stopWatch.Start(StopWatch::FrameworkTimer);
  1809. #endif
  1810. hr = WBEM_S_NO_ERROR;
  1811. }
  1812. // Clean up the Parsed Path
  1813. if (pParsedPath)
  1814. {
  1815. objpathParser.Free( pParsedPath );
  1816. }
  1817. Release();
  1818. #ifdef PROVIDER_INSTRUMENTATION
  1819. stopWatch.Stop();
  1820. stopWatch.LogResults();
  1821. #endif
  1822. return hr;
  1823. }
  1824. /////////////////////////////////////////////////////////////////////
  1825. //
  1826. // Function: CWbemProviderGlue::GetNamespaceConnection
  1827. //
  1828. // Establishes a connection to the supplied namespace by first
  1829. // assigning a default if needed, then searching our map, and if
  1830. // that fails, then actually connecting.
  1831. //
  1832. // Inputs: const BSTR NameSpace - NameSpace of provider
  1833. //
  1834. // Outputs: None.
  1835. //
  1836. // Returns: IWbemServices *pointer to IWbemServices corresponding
  1837. // to the connected namespace.
  1838. //
  1839. // Comments: Default Namespace is Root\\Default
  1840. //
  1841. //
  1842. /////////////////////////////////////////////////////////////////////
  1843. IWbemServices *CWbemProviderGlue::GetNamespaceConnection(
  1844. LPCWSTR pwszNameSpace
  1845. )
  1846. {
  1847. ASSERT_BREAK(DEPRECATED);
  1848. bstr_t bstrNamespace(pwszNameSpace);
  1849. // Root\CimV2 is the default name space
  1850. if ( NULL == pwszNameSpace
  1851. || L'\0' == *pwszNameSpace )
  1852. {
  1853. bstrNamespace = DEFAULT_NAMESPACE;
  1854. }
  1855. if (IsVerboseLoggingEnabled())
  1856. {
  1857. LogMessage3(L"%s%s", IDS_GETNAMESPACECONNECTION, (LPCWSTR)bstrNamespace);
  1858. }
  1859. IWbemLocatorPtr pIWbemLocator;
  1860. IWbemServices *pWbemServices = NULL;
  1861. HRESULT hRes = CoCreateInstance (
  1862. CLSID_WbemLocator, //CLSID_WbemAdministrativeLocator,
  1863. NULL,
  1864. CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
  1865. IID_IUnknown,
  1866. ( void ** ) &pIWbemLocator
  1867. ) ;
  1868. if (SUCCEEDED(hRes))
  1869. {
  1870. hRes = pIWbemLocator->ConnectServer(bstrNamespace, // Namespace
  1871. NULL, // Userid
  1872. NULL, // PW
  1873. NULL, // Locale
  1874. 0, // flags
  1875. NULL, // Authority
  1876. NULL, // Context
  1877. &pWbemServices
  1878. );
  1879. if (SUCCEEDED(hRes))
  1880. {
  1881. }
  1882. else
  1883. {
  1884. LogErrorMessage3(L"Failed to Connectserver to namespace %s (%x)", (LPCWSTR)bstrNamespace, hRes);
  1885. }
  1886. }
  1887. else
  1888. {
  1889. LogErrorMessage2(L"Failed to get locator (%x)", hRes);
  1890. }
  1891. return pWbemServices;
  1892. }
  1893. /////////////////////////////////////////////////////////////////////
  1894. //
  1895. // Function: CWbemProviderGlue::FrameworkLogin
  1896. //
  1897. // Static entry point for providers to login to the framework,
  1898. // providing us with info for our map, and allowing us to return
  1899. // an IWbemServices pointer for the base provider class to
  1900. // manipulate to its heart's content.
  1901. //
  1902. // Inputs: LPCWSTR& strName - Name of object for map.
  1903. // Provider *pProvider - Pointer Name Maps to.
  1904. // LPCWSTR pszNameSpace - NameSpace of provider
  1905. //
  1906. // Outputs: None.
  1907. //
  1908. // Returns: None.
  1909. //
  1910. // Comments: None.
  1911. //
  1912. //
  1913. /////////////////////////////////////////////////////////////////////
  1914. void CWbemProviderGlue::FrameworkLogin(
  1915. LPCWSTR a_szName,
  1916. Provider *a_pProvider,
  1917. LPCWSTR a_pszNameSpace
  1918. )
  1919. {
  1920. if (IsVerboseLoggingEnabled())
  1921. {
  1922. if (a_pszNameSpace != NULL)
  1923. {
  1924. LogMessage4(L"%s%s:%s", IDS_FRAMEWORKLOGIN, a_pszNameSpace, a_szName);
  1925. }
  1926. else
  1927. {
  1928. LogMessage4(L"%s%s:%s", IDS_FRAMEWORKLOGIN, DEFAULT_NAMESPACE, a_szName);
  1929. }
  1930. }
  1931. // AddProviderToMap, searches the Map for a match first.
  1932. // If one is found, it does not perform the actual add.
  1933. // Check that the pointers are the same. If they're
  1934. // different, this is what happened.
  1935. // pProvider doesn't get addref'ed, so no release necessary
  1936. Provider *t_pTestProvider = AddProviderToMap( a_szName, a_pszNameSpace, a_pProvider );
  1937. if ( t_pTestProvider != a_pProvider )
  1938. {
  1939. // this should never happen
  1940. // a provider should login only once at construction and out at destruction
  1941. // this should coincide with DLLs being loaded and unloaded.
  1942. LogErrorMessage4(L"%s (%s:%s)", IDS_LOGINDISALLOWED, a_pszNameSpace, a_szName);
  1943. ASSERT_BREAK( FALSE );
  1944. }
  1945. }
  1946. /////////////////////////////////////////////////////////////////////
  1947. //
  1948. // Function: CWbemProviderGlue::FrameworkLogoff
  1949. //
  1950. // Static entry point for providers to log out of the framework,
  1951. // this should be called from the provider's dtor so that we release
  1952. // all of our pointers so they don't dangle.
  1953. //
  1954. // Inputs: LPCWSTR& strName - Name of object for map.
  1955. // LPCWSTR pszNameSpace - NameSpace of provider
  1956. //
  1957. // Outputs: None.
  1958. //
  1959. // Returns: usually.
  1960. //
  1961. // Comments: We don't bother removing entries from the namespace map.
  1962. //
  1963. //
  1964. /////////////////////////////////////////////////////////////////////
  1965. void CWbemProviderGlue::FrameworkLogoff(
  1966. LPCWSTR a_pszName,
  1967. LPCWSTR a_pszNamespace
  1968. )
  1969. {
  1970. STRING2LPVOID::iterator mapIter;
  1971. if (IsVerboseLoggingEnabled())
  1972. {
  1973. LogMessage3(L"%s%s", IDS_FRAMEWORKLOGOFF, a_pszName);
  1974. }
  1975. CHString strQualifiedName( a_pszName );
  1976. // If our NameSpace is non-NULL (we use DEFAULT_NAMESPACE then), AND it
  1977. // is not DEFAULT_NAMESPACE, concat the namespace to the provider name
  1978. // so we can differentiate providers across namespaces.
  1979. if ( (a_pszNamespace != NULL) && (a_pszNamespace[0] != L'\0')
  1980. && 0 != _wcsicmp(a_pszNamespace, DEFAULT_NAMESPACE ) )
  1981. {
  1982. strQualifiedName += a_pszNamespace;
  1983. }
  1984. // Convert characters to upper case before searching for
  1985. // them in the map. Since we convert to upper case when
  1986. // we store the map associations, this effectively makes
  1987. // us case-insensitive.
  1988. strQualifiedName.MakeUpper();
  1989. LockProviderMap();
  1990. try
  1991. {
  1992. if( ( mapIter = s_providersmap.find( strQualifiedName ) ) != s_providersmap.end() )
  1993. s_providersmap.erase(mapIter);
  1994. else
  1995. ASSERT_BREAK(0 /* did not find provider to log off!*/);
  1996. }
  1997. catch ( ... )
  1998. {
  1999. UnlockProviderMap();
  2000. throw;
  2001. }
  2002. UnlockProviderMap();
  2003. }
  2004. /////////////////////////////////////////////////////////////////////
  2005. //
  2006. // Function: CWbemProviderGlue::GetAllInstances
  2007. //
  2008. // Static entry point for providers to obtain instance lists from
  2009. // other providers.
  2010. //
  2011. // Inputs: LPCWSTR pszProviderName - Name of provider to
  2012. // get list for.
  2013. // TRefPointerCollection<CInstance> *pList - List to fill.
  2014. // LPCWSTR pszNamespace - Namespace of provider.
  2015. //
  2016. // Outputs: None.
  2017. //
  2018. // Returns: HRESULT hr - Status code.
  2019. //
  2020. // Comments: This is an internal entry point, allowing providers
  2021. // to short circuit having to go through WBEM to access
  2022. // data from other providers.
  2023. //
  2024. /////////////////////////////////////////////////////////////////////
  2025. HRESULT WINAPI CWbemProviderGlue::GetAllInstances(
  2026. LPCWSTR pszClassName,
  2027. TRefPointerCollection<CInstance> *pList,
  2028. LPCWSTR pszNamespace, /* = NULL*/
  2029. MethodContext *pMethodContext /* = NULL*/
  2030. )
  2031. {
  2032. HRESULT hr = WBEM_S_NO_ERROR;
  2033. PROVIDER_INSTRUMENTATION_START(pMethodContext, StopWatch::FrameworkTimer);
  2034. if (pszClassName)
  2035. {
  2036. CHString sQuery;
  2037. sQuery.Format(L"SELECT * FROM %s where __CLASS = \"%s\"", pszClassName, pszClassName);
  2038. hr = GetInstancesByQuery( sQuery, pList, pMethodContext, pszNamespace);
  2039. }
  2040. else
  2041. {
  2042. hr = WBEM_E_INVALID_PARAMETER;
  2043. }
  2044. PROVIDER_INSTRUMENTATION_START(pMethodContext, StopWatch::ProviderTimer);
  2045. return hr;
  2046. }
  2047. /////////////////////////////////////////////////////////////////////
  2048. //
  2049. // Function: CWbemProviderGlue::GetAllInstancesAsynch
  2050. //
  2051. // Static entry point for providers to obtain instances from
  2052. // other providers. Note that this is not, strictly speaking,
  2053. // an asynchronous implementation - it does HELP the asynch calls
  2054. // in that it does not build a big list and that the callback allows
  2055. // the provider to respond asynchronously
  2056. //
  2057. // Inputs: LPCWSTR pszProviderName - Name of provider to
  2058. // get instances from.
  2059. //
  2060. // Provider * this is the "this" pointer for the requester
  2061. // LPProviderInstanceCallback callback function to eat the instances provided
  2062. // LPCWSTR pszNamespace - Namespace of provider.
  2063. //
  2064. // Outputs: None.
  2065. //
  2066. // Returns: HRESULT hr - Status code.
  2067. //
  2068. // Comments: This is an internal entry point, allowing providers
  2069. // to short circuit having to go through WBEM to access
  2070. // data from other providers.
  2071. // this puppy shares a lot of code with GetAllInstances, but I
  2072. // can't find a clean way to combine them.
  2073. //
  2074. /////////////////////////////////////////////////////////////////////
  2075. HRESULT WINAPI CWbemProviderGlue::GetAllInstancesAsynch(
  2076. LPCWSTR pszClassName,
  2077. Provider *pRequester,
  2078. LPProviderInstanceCallback pCallback,
  2079. LPCWSTR pszNamespace,
  2080. MethodContext *pMethodContext,
  2081. void *pUserData
  2082. )
  2083. {
  2084. PROVIDER_INSTRUMENTATION_START(pMethodContext, StopWatch::FrameworkTimer);
  2085. HRESULT hr = WBEM_S_NO_ERROR;
  2086. if (pszClassName)
  2087. {
  2088. CHString sQuery;
  2089. sQuery.Format(L"SELECT * FROM %s where __CLASS = \"%s\"", pszClassName, pszClassName);
  2090. hr = GetInstancesByQueryAsynch( sQuery, pRequester, pCallback, pszNamespace, pMethodContext, pUserData);
  2091. PROVIDER_INSTRUMENTATION_START(pMethodContext, StopWatch::ProviderTimer);
  2092. }
  2093. else
  2094. {
  2095. hr = WBEM_E_INVALID_PARAMETER;
  2096. }
  2097. return hr;
  2098. }
  2099. /////////////////////////////////////////////////////////////////////
  2100. //
  2101. // Function: CWbemProviderGlue::GetAllDerivedInstances
  2102. //
  2103. // Static entry point for providers to obtain instance lists from
  2104. // other providers. This one will return all instances derived from
  2105. // the base class passed in.
  2106. //
  2107. // Inputs: LPCWSTR pszBaseClassName - Name of base class
  2108. // to get list for.
  2109. // TRefPointerCollection<CInstance> *pList - List to fill.
  2110. // LPCWSTR pszNamespace - Namespace of provider.
  2111. // MethodContext *pMethodContext, // must not be NULL
  2112. //
  2113. // Outputs: None.
  2114. //
  2115. // Returns: HRESULT hr - Status code.
  2116. //
  2117. // Comments: This is an internal entry point, allowing providers
  2118. // to short circuit having to go through WBEM to access
  2119. // data from other providers.
  2120. //
  2121. /////////////////////////////////////////////////////////////////////
  2122. HRESULT WINAPI CWbemProviderGlue::GetAllDerivedInstances(
  2123. LPCWSTR pszBaseClassName,
  2124. TRefPointerCollection<CInstance> *pList,
  2125. MethodContext *pMethodContext,
  2126. LPCWSTR pszNamespace
  2127. )
  2128. {
  2129. PROVIDER_INSTRUMENTATION_START(pMethodContext, StopWatch::FrameworkTimer);
  2130. HRESULT hr = WBEM_S_NO_ERROR;
  2131. if (pszBaseClassName)
  2132. {
  2133. CHString sQuery;
  2134. sQuery.Format(L"SELECT * FROM %s", pszBaseClassName);
  2135. hr = GetInstancesByQuery( sQuery, pList, pMethodContext, pszNamespace);
  2136. }
  2137. else
  2138. {
  2139. hr = WBEM_E_INVALID_PARAMETER;
  2140. }
  2141. PROVIDER_INSTRUMENTATION_START(pMethodContext, StopWatch::ProviderTimer);
  2142. return hr;
  2143. }
  2144. /////////////////////////////////////////////////////////////////////
  2145. //
  2146. // Function: CWbemProviderGlue::GetAllDerivedInstancesAsynch
  2147. //
  2148. // Static entry point for providers to obtain instances from
  2149. // other providers. Note that this is not, strictly speaking,
  2150. // an asynchronous implementation - it does HELP the asynch calls
  2151. // in that it does not build a big list and that the callback allows
  2152. // the provider to respond asynchronously
  2153. //
  2154. // Inputs: LPCWSTR pszProviderName - Name of provider to
  2155. // get instances from.
  2156. //
  2157. // Provider* this is the "this" pointer for the requester
  2158. // LPProviderInstanceCallback callback function to eat the instances provided
  2159. // LPCWSTR pszNamespace - Namespace of provider.
  2160. //
  2161. // Outputs: None.
  2162. //
  2163. // Returns: HRESULT hr - Status code.
  2164. //
  2165. // Comments: This is an internal entry point, allowing providers
  2166. // to short circuit having to go through WBEM to access
  2167. // data from other providers.
  2168. // this puppy shares a lot of code with GetAllInstances, but I
  2169. // can't find a clean way to combine them.
  2170. //
  2171. /////////////////////////////////////////////////////////////////////
  2172. HRESULT WINAPI CWbemProviderGlue::GetAllDerivedInstancesAsynch(
  2173. LPCWSTR pszProviderName,
  2174. Provider *pRequester,
  2175. LPProviderInstanceCallback pCallback,
  2176. LPCWSTR pszNamespace,
  2177. MethodContext *pMethodContext,
  2178. void *pUserData
  2179. )
  2180. {
  2181. PROVIDER_INSTRUMENTATION_START(pMethodContext, StopWatch::FrameworkTimer);
  2182. HRESULT hr = WBEM_S_NO_ERROR;
  2183. if (pszProviderName)
  2184. {
  2185. CHString sQuery;
  2186. sQuery.Format(L"SELECT * FROM %s", pszProviderName);
  2187. hr = GetInstancesByQueryAsynch( sQuery, pRequester, pCallback, pszNamespace, pMethodContext, pUserData);
  2188. }
  2189. else
  2190. {
  2191. hr = WBEM_E_INVALID_PARAMETER;
  2192. }
  2193. PROVIDER_INSTRUMENTATION_START(pMethodContext, StopWatch::ProviderTimer);
  2194. return hr;
  2195. }
  2196. /////////////////////////////////////////////////////////////////////
  2197. //
  2198. // Function: CWbemProviderGlue::GetInstancesByQuery
  2199. //
  2200. // Static entry point for providers to obtain instance lists from
  2201. // other providers. This one will return all instances matching a query.
  2202. //
  2203. // Inputs: LPCWSTR Query to execute "Select * from win32_foo where bar = "baz""
  2204. // TRefPointerCollection<CInstance> *pList - List to fill.
  2205. // MethodContext *pMethodContext, // must not be NULL
  2206. // LPCWSTR pointer to namespace - may be NULL (means default -- root\cimv2)
  2207. //
  2208. // Outputs: None.
  2209. //
  2210. // Returns: HRESULT hr - Status code.
  2211. //
  2212. /////////////////////////////////////////////////////////////////////
  2213. HRESULT WINAPI CWbemProviderGlue::GetInstancesByQuery( LPCWSTR query,
  2214. TRefPointerCollection<CInstance> *pList,
  2215. MethodContext *pMethodContext,
  2216. LPCWSTR pszNamespace /* = NULL*/)
  2217. {
  2218. PROVIDER_INSTRUMENTATION_START(pMethodContext, StopWatch::FrameworkTimer);
  2219. if (IsVerboseLoggingEnabled())
  2220. {
  2221. LogMessage3(L"%s (%s)", IDS_GETINSTANCESBYQUERY, query);
  2222. }
  2223. HRESULT hr = WBEM_E_FAILED;
  2224. if ( (query != NULL) &&
  2225. (pList != NULL) &&
  2226. (pMethodContext != NULL) )
  2227. {
  2228. IEnumWbemClassObjectPtr pEnum;
  2229. IWbemContextPtr pWbemContext;
  2230. if (pMethodContext)
  2231. {
  2232. pWbemContext.Attach(pMethodContext->GetIWBEMContext());
  2233. }
  2234. IWbemServicesPtr piService;
  2235. // get a service interface
  2236. if (pszNamespace == NULL || pszNamespace[0] == L'\0')
  2237. {
  2238. piService.Attach(GetNamespaceConnection(NULL, pMethodContext));
  2239. }
  2240. else
  2241. {
  2242. piService.Attach(GetNamespaceConnection( pszNamespace, pMethodContext));
  2243. }
  2244. if ( piService != NULL)
  2245. {
  2246. {
  2247. // Assures that impersonation goes
  2248. // back to the way it was before the
  2249. // call to CIMOM.
  2250. CAutoImpRevert air;
  2251. DWORD dwImpErr = air.LastError();
  2252. if(dwImpErr == ERROR_SUCCESS)
  2253. {
  2254. PROVIDER_INSTRUMENTATION_START(pMethodContext, StopWatch::WinMgmtTimer);
  2255. hr = piService->ExecQuery(bstr_t(IDS_WQL), bstr_t(query), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, pWbemContext, &pEnum);
  2256. PROVIDER_INSTRUMENTATION_START(pMethodContext, StopWatch::FrameworkTimer);
  2257. }
  2258. else
  2259. {
  2260. LogErrorMessage2(L"Failed to open current thread token for checking impersonation, with error %d", dwImpErr);
  2261. hr = WBEM_E_FAILED;
  2262. }
  2263. }
  2264. if ( SUCCEEDED( hr ) )
  2265. {
  2266. IWbemClassObjectPtr pObj;
  2267. ULONG nReturned;
  2268. // author's apology:
  2269. // we loop through, using Next() to get each instance
  2270. // we bail when we get WBEM_S_FALSE because that's the end of the enumeration
  2271. PROVIDER_INSTRUMENTATION_START(pMethodContext, StopWatch::WinMgmtTimer);
  2272. for (hr = pEnum->Next(GLUETIMEOUT, 1, &pObj, &nReturned);
  2273. (SUCCEEDED(hr) && (hr != WBEM_S_FALSE) && (hr != WBEM_S_TIMEDOUT) ) ;
  2274. hr = pEnum->Next(GLUETIMEOUT, 1, &pObj, &nReturned))
  2275. {
  2276. PROVIDER_INSTRUMENTATION_START(pMethodContext, StopWatch::FrameworkTimer);
  2277. if (pObj != NULL && nReturned)
  2278. {
  2279. CInstancePtr pInstance(new CInstance(pObj, pMethodContext), false);
  2280. if (pInstance != NULL)
  2281. {
  2282. // Check to see if adding to the list succeeds
  2283. if (!pList->Add(pInstance))
  2284. {
  2285. hr = WBEM_E_OUT_OF_MEMORY;
  2286. }
  2287. }
  2288. else
  2289. {
  2290. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  2291. }
  2292. }
  2293. }
  2294. PROVIDER_INSTRUMENTATION_START(pMethodContext, StopWatch::FrameworkTimer);
  2295. // the Next will return WBEM_S_FALSE when it is done. However, that
  2296. // means that THIS function had no error.
  2297. if (hr == WBEM_S_FALSE)
  2298. {
  2299. hr = WBEM_S_NO_ERROR;
  2300. }
  2301. // fencepost check - the last error might have been access denied
  2302. // but it's okay if we got any instances at all
  2303. else if (hr == WBEM_E_ACCESS_DENIED)
  2304. if (pList->GetSize() > 0)
  2305. hr = WBEM_S_NO_ERROR;
  2306. } // IF SUCCEEDED
  2307. }
  2308. else
  2309. LogErrorMessage(IDS_FAILED);
  2310. }
  2311. else
  2312. {
  2313. hr = WBEM_E_INVALID_PARAMETER;
  2314. LogErrorMessage(L"NULL parameter to GetInstancesByQuery");
  2315. ASSERT_BREAK(WBEM_E_INVALID_PARAMETER);
  2316. }
  2317. if (IsVerboseLoggingEnabled())
  2318. {
  2319. if (SUCCEEDED(hr))
  2320. {
  2321. LogMessage3(L"%s (%s) - Succeeded", IDS_GETINSTANCESBYQUERY, query);
  2322. }
  2323. else
  2324. {
  2325. LogMessage4(L"%s (%s) - FAILED (%x)", IDS_GETINSTANCESBYQUERY, query, hr);
  2326. }
  2327. }
  2328. PROVIDER_INSTRUMENTATION_START(pMethodContext, StopWatch::ProviderTimer);
  2329. return hr;
  2330. }
  2331. /////////////////////////////////////////////////////////////////////
  2332. //
  2333. // Function: CWbemProviderGlue::IsDerivedFrom
  2334. //
  2335. // Static entry point for providers to obtain derivation information
  2336. //
  2337. // Inputs: LPCWSTR pszBaseClassName - Name of base class
  2338. // LPCWSTR pszDerivedClassName - Name of class we're testing
  2339. // MethodContext *pMethodContext
  2340. //
  2341. // Outputs: None.
  2342. //
  2343. // Returns: true iff pszDerivedClassName is derived from pszBaseClassName
  2344. //
  2345. // Comments: This function cannot short circuit, because a derived class may be external
  2346. //
  2347. /////////////////////////////////////////////////////////////////////
  2348. bool CWbemProviderGlue::IsDerivedFrom(
  2349. LPCWSTR pszBaseClassName,
  2350. LPCWSTR pszDerivedClassName,
  2351. MethodContext *pMethodContext,
  2352. LPCWSTR pszNamespace /* = NULL*/
  2353. )
  2354. {
  2355. PROVIDER_INSTRUMENTATION_START(pMethodContext, StopWatch::FrameworkTimer);
  2356. bool bRet = false;
  2357. if ( (pszBaseClassName != NULL) &&
  2358. (pszDerivedClassName != NULL) &&
  2359. (pMethodContext != NULL) )
  2360. {
  2361. IWbemServicesPtr piService;
  2362. // get a service interface
  2363. piService.Attach(GetNamespaceConnection( pszNamespace, pMethodContext ));
  2364. // find the derived class object
  2365. if (piService != NULL)
  2366. {
  2367. IWbemClassObjectPtr pObj;
  2368. IWbemContextPtr pWbemContext;
  2369. if (pMethodContext)
  2370. {
  2371. pWbemContext.Attach(pMethodContext->GetIWBEMContext());
  2372. }
  2373. PROVIDER_INSTRUMENTATION_START(pMethodContext, StopWatch::WinMgmtTimer);
  2374. HRESULT hr = piService->GetObject( bstr_t( pszDerivedClassName ), 0, pWbemContext, &pObj, NULL);
  2375. PROVIDER_INSTRUMENTATION_START(pMethodContext, StopWatch::FrameworkTimer);
  2376. if (SUCCEEDED(hr) && (pObj != NULL))
  2377. {
  2378. // Variant_t handles the VariantInit/VariantClear
  2379. variant_t v;
  2380. if (SUCCEEDED(pObj->Get((unsigned short *)IDS_DERIVATION, 0, &v, NULL, NULL)))
  2381. {
  2382. BSTR bstrTemp = NULL;
  2383. SAFEARRAY *psa = V_ARRAY(&v);
  2384. LONG uBound;
  2385. SafeArrayGetUBound(psa, 1, &uBound);
  2386. // if base class is in the list in the derivation, we're true!
  2387. for (LONG i = 0; !bRet && (i <= uBound); i++)
  2388. {
  2389. SafeArrayGetElement(psa, &i, &bstrTemp);
  2390. try
  2391. {
  2392. bRet = (_wcsicmp(pszBaseClassName, bstrTemp) == 0);
  2393. }
  2394. catch ( ... )
  2395. {
  2396. SysFreeString(bstrTemp);
  2397. throw ;
  2398. }
  2399. SysFreeString(bstrTemp);
  2400. }
  2401. }
  2402. }
  2403. }
  2404. }
  2405. else
  2406. {
  2407. LogErrorMessage(L"NULL parameter to IsDerivedFrom");
  2408. ASSERT_BREAK(WBEM_E_INVALID_PARAMETER);
  2409. }
  2410. PROVIDER_INSTRUMENTATION_START(pMethodContext, StopWatch::ProviderTimer);
  2411. return bRet;
  2412. }
  2413. /////////////////////////////////////////////////////////////////////
  2414. //
  2415. // Function: CWbemProviderGlue::GetEmptyInstance
  2416. //
  2417. // Static entry point for providers to obtain a single empty instance
  2418. // of a provider object.
  2419. //
  2420. // Inputs: LPCWSTR pszProviderName - Name of provider to
  2421. // get list for.
  2422. // LPCWSTR pszNamespace - Namespace of provider.
  2423. //
  2424. // Outputs: CInstance **ppInstance - Pointer to store new
  2425. // pInstance in. Must be Released by
  2426. // caller.
  2427. //
  2428. // Returns: HRESULT hr - Status code.
  2429. //
  2430. // Comments: This is an internal entry point, allowing providers
  2431. // to short circuit having to go through WBEM to access
  2432. // data from other providers.
  2433. //
  2434. /////////////////////////////////////////////////////////////////////
  2435. // DEPRECATED
  2436. HRESULT WINAPI CWbemProviderGlue::GetEmptyInstance(
  2437. LPCWSTR pszClassName,
  2438. CInstance **ppInstance,
  2439. LPCWSTR pszNamespace
  2440. )
  2441. {
  2442. ASSERT_BREAK(DEPRECATED);
  2443. HRESULT hr = WBEM_E_INVALID_CLASS;
  2444. if ( (pszClassName != NULL) &&
  2445. (ppInstance != NULL) )
  2446. {
  2447. // Search for the class name in our map of providers, we know which
  2448. // namespace we are when we get constructed.
  2449. // pProvider doesn't get addref'ed, so no release is necessary
  2450. Provider *pProvider = SearchMapForProvider( pszClassName, pszNamespace );
  2451. if ( NULL != pProvider )
  2452. {
  2453. // Now create an Internal Method Context object, since this function
  2454. // only gets called internal to our DLL. Using a NULL for the
  2455. // list pointer, essentially creates a dummy context so we can
  2456. // do our commit dance as painlessly as possible.
  2457. InternalMethodContextPtr pContext (new InternalMethodContext( NULL, NULL, NULL ), false);
  2458. if ( NULL != pContext )
  2459. {
  2460. // Assume things will go wrong like a good liitle paranoiac
  2461. hr = WBEM_E_FAILED;
  2462. // Before asking for a new instance, we MUST verify that the
  2463. // provider has a valid IMOS pointer. If it does'nt, CreateNewInstance
  2464. // may GPF (this is a safety check we must do because of our
  2465. // little short circuit.
  2466. // We don't do short circuits anymore.
  2467. // if ( pProvider->ValidateIMOSPointer() )
  2468. {
  2469. // Set the error code appropriately depending on whether or
  2470. // not the Instance gets created correctly.
  2471. // The instance returned will have been AddRefed, so it will
  2472. // be up to the caller to Release() it.
  2473. if ( ( *ppInstance = pProvider->CreateNewInstance( pContext ) ) != NULL )
  2474. {
  2475. hr = WBEM_S_NO_ERROR;
  2476. }
  2477. }
  2478. }
  2479. else
  2480. {
  2481. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  2482. }
  2483. }
  2484. else
  2485. {
  2486. hr = WBEM_E_INVALID_CLASS;
  2487. }
  2488. }
  2489. else
  2490. {
  2491. hr = WBEM_E_INVALID_PARAMETER;
  2492. LogErrorMessage(L"NULL parameter to GetEmptyInstance");
  2493. ASSERT_BREAK(WBEM_E_INVALID_PARAMETER);
  2494. }
  2495. return hr;
  2496. }
  2497. /////////////////////////////////////////////////////////////////////
  2498. //
  2499. // Function: CWbemProviderGlue::GetEmptyInstance
  2500. //
  2501. // Static entry point for providers to obtain a single empty instance
  2502. // of a provider object. This alternate form makes a call back
  2503. // into WINMGMT.
  2504. //
  2505. // Inputs: MethodContext *Context object for this call
  2506. // LPCWSTR pszProviderName - Name of provider to
  2507. // get instance of.
  2508. // LPCWSTR pszNamespace - Namespace of class.
  2509. //
  2510. // Outputs: CInstance **ppInstance - Pointer to store new
  2511. // pInstance in. Must be Released by
  2512. // caller.
  2513. //
  2514. // Returns: HRESULT hr - Status code.
  2515. //
  2516. // Comments:
  2517. //
  2518. /////////////////////////////////////////////////////////////////////
  2519. HRESULT WINAPI CWbemProviderGlue::GetEmptyInstance(
  2520. MethodContext *pMethodContext,
  2521. LPCWSTR pszProviderName,
  2522. CInstance **ppOutInstance,
  2523. LPCWSTR a_pszNamespace
  2524. )
  2525. {
  2526. PROVIDER_INSTRUMENTATION_START(pMethodContext, StopWatch::FrameworkTimer);
  2527. HRESULT hr = WBEM_E_FAILED;
  2528. if ( (pMethodContext != NULL) &&
  2529. (pszProviderName != NULL) &&
  2530. (ppOutInstance != NULL) )
  2531. {
  2532. CInstancePtr pClassInstance;
  2533. hr = GetInstanceFromCIMOM(pszProviderName, a_pszNamespace, pMethodContext, &pClassInstance);
  2534. if (SUCCEEDED(hr))
  2535. {
  2536. IWbemClassObjectPtr pClassObject(pClassInstance->GetClassObjectInterface(), false);
  2537. if (pClassObject != NULL)
  2538. {
  2539. IWbemClassObjectPtr pObj;
  2540. hr = pClassObject->SpawnInstance(0, &pObj);
  2541. if (SUCCEEDED(hr))
  2542. {
  2543. *ppOutInstance = new CInstance(pObj, pMethodContext);
  2544. if (*ppOutInstance == NULL)
  2545. {
  2546. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  2547. }
  2548. }
  2549. }
  2550. else
  2551. {
  2552. hr = WBEM_E_FAILED;
  2553. }
  2554. }
  2555. }
  2556. else
  2557. {
  2558. hr = WBEM_E_INVALID_PARAMETER;
  2559. LogErrorMessage(L"NULL parameter to GetEmptyInstance");
  2560. ASSERT_BREAK(WBEM_E_INVALID_PARAMETER);
  2561. }
  2562. PROVIDER_INSTRUMENTATION_START(pMethodContext, StopWatch::ProviderTimer);
  2563. return hr;
  2564. }
  2565. /////////////////////////////////////////////////////////////////////
  2566. //
  2567. // Function: CWbemProviderGlue::FillInstance
  2568. //
  2569. // Static entry point for providers to pass us an instance with
  2570. // key data filled out, which we will use to locate the correct
  2571. // provider and ask it to fill out completely.
  2572. //
  2573. // Inputs: CInstance *pInstance - Instance to fill out.
  2574. // LPCWSTR pszNamespace - Namespace for provider.
  2575. //
  2576. // Outputs: None.
  2577. //
  2578. // Returns: HRESULT hr - Status code.
  2579. //
  2580. // Comments: This is an internal entry point, allowing providers
  2581. // to short circuit having to go through WBEM to access
  2582. // data from other providers.
  2583. //
  2584. /////////////////////////////////////////////////////////////////////
  2585. // DEPRECATED!
  2586. HRESULT WINAPI CWbemProviderGlue::FillInstance(
  2587. CInstance *pInstance,
  2588. LPCWSTR pszNamespace /*= NULL*/
  2589. )
  2590. {
  2591. ASSERT_BREAK(DEPRECATED);
  2592. HRESULT hr = WBEM_E_FAILED;
  2593. if (pInstance != NULL)
  2594. {
  2595. // Check that we have an instance pointer, then pull out the
  2596. // class name and name space. From there we can find the
  2597. // appropriate provider and ask it to get the object.
  2598. if ( NULL != pInstance )
  2599. {
  2600. CHString strProviderName;
  2601. pInstance->GetCHString( IDS_CLASS, strProviderName );
  2602. // Search for the class name in our map of providers, we know which
  2603. // namespace we are when we get constructed.
  2604. // pProvider is not addref'ed, so no release is necessary
  2605. Provider *pProvider = SearchMapForProvider( strProviderName, pszNamespace );
  2606. if ( NULL != pProvider )
  2607. {
  2608. // Pass the pInstance off to the provider and let it take care
  2609. // of obtaining the correct values.
  2610. hr = pProvider->GetObject( pInstance );
  2611. }
  2612. else
  2613. {
  2614. hr = WBEM_E_INVALID_CLASS;
  2615. }
  2616. }
  2617. }
  2618. else
  2619. {
  2620. hr = WBEM_E_INVALID_PARAMETER;
  2621. LogErrorMessage(L"NULL parameter to FillInstance");
  2622. ASSERT_BREAK(WBEM_E_INVALID_PARAMETER);
  2623. }
  2624. return hr;
  2625. }
  2626. /////////////////////////////////////////////////////////////////////
  2627. //
  2628. // Function: CWbemProviderGlue::FillInstance
  2629. //
  2630. // Static entry point for providers to pass us an instance with
  2631. // key data filled out, use to make a call back into winmgmt.
  2632. //
  2633. // Inputs: MethodContext *Context object for this call
  2634. // CInstance *pInstance - Instance to fill out.
  2635. //
  2636. // Outputs: None.
  2637. //
  2638. // Returns: HRESULT hr - Status code.
  2639. //
  2640. // Comments:
  2641. //
  2642. /////////////////////////////////////////////////////////////////////
  2643. HRESULT WINAPI CWbemProviderGlue::FillInstance(
  2644. MethodContext *pMethodContext,
  2645. CInstance *pInstance
  2646. )
  2647. {
  2648. ASSERT_BREAK(DEPRECATED);
  2649. HRESULT hr = WBEM_E_FAILED;
  2650. if ( (pMethodContext != NULL) &&
  2651. (pInstance != NULL) )
  2652. {
  2653. // Check that we have an instance pointer, then pull out the path
  2654. // and send it to cimom.
  2655. CHString strPathName;
  2656. pInstance->GetCHString( L"__RELPATH", strPathName );
  2657. hr = GetInstanceByPath(strPathName, &pInstance, pMethodContext);
  2658. }
  2659. else
  2660. {
  2661. hr = WBEM_E_INVALID_PARAMETER;
  2662. LogErrorMessage(L"NULL parameter to FillInstance");
  2663. ASSERT_BREAK(WBEM_E_INVALID_PARAMETER);
  2664. }
  2665. return hr;
  2666. }
  2667. /////////////////////////////////////////////////////////////////////
  2668. //
  2669. // Function: CWbemProviderGlue::GetInstanceKeysByPath
  2670. //
  2671. // Static entry point for providers to pass us an instance path
  2672. // to retrieve. This class uses per-property gets to request
  2673. // only the keys on the object we are retrieving.
  2674. //
  2675. // Inputs: pszInstancePath Object path to retrieve
  2676. // CInstance *pInstance - Instance to fill out.
  2677. // MethodContext *Context object for this call
  2678. //
  2679. // Outputs: None
  2680. //
  2681. // Returns: HRESULT hr - Status code.
  2682. //
  2683. // Comments:
  2684. //
  2685. /////////////////////////////////////////////////////////////////////
  2686. HRESULT WINAPI CWbemProviderGlue::GetInstanceKeysByPath(
  2687. LPCWSTR pszInstancePath,
  2688. CInstance **ppInstance,
  2689. MethodContext *pMethodContext
  2690. )
  2691. {
  2692. HRESULT hr = WBEM_S_NO_ERROR;
  2693. if ( (pMethodContext != NULL) &&
  2694. (pszInstancePath != NULL) &&
  2695. (ppInstance != NULL) )
  2696. {
  2697. IWbemContextPtr pWbemContext(pMethodContext->GetIWBEMContext(), false);
  2698. // We need to have a real context object, not an internal method context
  2699. if (pWbemContext != NULL)
  2700. {
  2701. VARIANT vValue;
  2702. V_VT(&vValue) = VT_BOOL;
  2703. V_BOOL(&vValue) = VARIANT_TRUE;
  2704. // Set the appropriate properties on the context object
  2705. if ( (SUCCEEDED(hr = pWbemContext->SetValue(L"__GET_EXTENSIONS", 0L, &vValue))) &&
  2706. (SUCCEEDED(hr = pWbemContext->SetValue(L"__GET_EXT_KEYS_ONLY", 0L, &vValue))) &&
  2707. (SUCCEEDED(hr = pWbemContext->SetValue(L"__GET_EXT_CLIENT_REQUEST", 0L, &vValue))))
  2708. {
  2709. LogMessage2(L"GetInstanceKeysByPath: %s", pszInstancePath);
  2710. hr = GetInstanceByPath(pszInstancePath, ppInstance, pMethodContext);
  2711. V_BOOL(&vValue) = VARIANT_FALSE;
  2712. pWbemContext->SetValue(L"__GET_EXTENSIONS", 0L, &vValue);
  2713. }
  2714. }
  2715. else
  2716. {
  2717. ASSERT_BREAK(FALSE);
  2718. LogErrorMessage(L"Can't use InternalMethodContext to GetInstanceKeysByPath");
  2719. hr = WBEM_E_INVALID_PARAMETER;
  2720. }
  2721. }
  2722. else
  2723. {
  2724. hr = WBEM_E_INVALID_PARAMETER;
  2725. }
  2726. return hr;
  2727. }
  2728. /////////////////////////////////////////////////////////////////////
  2729. //
  2730. // Function: CWbemProviderGlue::GetInstancePropertiesByPath
  2731. //
  2732. // Static entry point for providers to pass us an instance path
  2733. // to retrieve. This class uses per-property gets to request
  2734. // only the properties specified in the array.
  2735. //
  2736. // Inputs: pszInstancePath Object path to retrieve
  2737. // CInstance *pInstance - Instance to fill out.
  2738. // MethodContext *Context object for this call
  2739. // csaProperties Properties to request
  2740. //
  2741. // Outputs: None
  2742. //
  2743. // Returns: HRESULT hr - Status code.
  2744. //
  2745. // Comments:
  2746. //
  2747. /////////////////////////////////////////////////////////////////////
  2748. HRESULT WINAPI CWbemProviderGlue::GetInstancePropertiesByPath(
  2749. LPCWSTR pszInstancePath,
  2750. CInstance **ppInstance,
  2751. MethodContext *pMethodContext,
  2752. CHStringArray &csaProperties
  2753. )
  2754. {
  2755. HRESULT hr = WBEM_S_NO_ERROR;
  2756. if ( (pMethodContext != NULL) &&
  2757. (pszInstancePath != NULL) &&
  2758. (ppInstance != NULL) )
  2759. {
  2760. IWbemContextPtr pWbemContext(pMethodContext->GetIWBEMContext(), false);
  2761. // We need to have a real context object, not an internal method context
  2762. if (pWbemContext != NULL)
  2763. {
  2764. variant_t vValue;
  2765. V_VT(&vValue) = VT_BOOL;
  2766. V_BOOL(&vValue) = VARIANT_TRUE;
  2767. // First set the value that says we are using Get extensions
  2768. if ((SUCCEEDED(hr = pWbemContext->SetValue(L"__GET_EXTENSIONS", 0L, &vValue))) &&
  2769. (SUCCEEDED(hr = pWbemContext->SetValue(L"__GET_EXT_CLIENT_REQUEST", 0L, &vValue))) )
  2770. {
  2771. // Delete any unneeded properties
  2772. pWbemContext->DeleteValue(L"__GET_EXT_KEYS_ONLY", 0L);
  2773. // Now build the array of properties
  2774. SAFEARRAYBOUND rgsabound [ 1 ] ;
  2775. rgsabound[0].cElements = csaProperties.GetSize() ;
  2776. rgsabound[0].lLbound = 0 ;
  2777. V_ARRAY(&vValue) = SafeArrayCreate ( VT_BSTR, 1, rgsabound ) ;
  2778. if ( V_ARRAY(&vValue) )
  2779. {
  2780. V_VT(&vValue) = VT_BSTR | VT_ARRAY;
  2781. for (long x=0; x < csaProperties.GetSize(); x++)
  2782. {
  2783. bstr_t bstrProp = csaProperties[x];
  2784. SafeArrayPutElement(
  2785. V_ARRAY(&vValue),
  2786. &x,
  2787. (LPVOID) (BSTR) bstrProp);
  2788. }
  2789. // Put the array into the context object
  2790. if (SUCCEEDED(hr = pWbemContext->SetValue(L"__GET_EXT_PROPERTIES", 0L, &vValue)))
  2791. {
  2792. LogMessage2(L"GetInstancePropertiesByPath: %s", pszInstancePath);
  2793. // Make the call
  2794. hr = GetInstanceByPath(pszInstancePath, ppInstance, pMethodContext);
  2795. vValue.Clear();
  2796. V_VT(&vValue) = VT_BOOL;
  2797. V_BOOL(&vValue) = VARIANT_FALSE;
  2798. pWbemContext->SetValue(L"__GET_EXTENSIONS", 0L, &vValue);
  2799. }
  2800. }
  2801. else
  2802. {
  2803. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  2804. }
  2805. }
  2806. }
  2807. else
  2808. {
  2809. ASSERT_BREAK(FALSE);
  2810. LogErrorMessage(L"Can't use InternalMethodContext to GetInstanceKeysByPath");
  2811. hr = WBEM_E_INVALID_PARAMETER;
  2812. }
  2813. }
  2814. else
  2815. {
  2816. hr = WBEM_E_INVALID_PARAMETER;
  2817. }
  2818. return hr;
  2819. }
  2820. /////////////////////////////////////////////////////////////////////
  2821. //
  2822. // Function: CWbemProviderGlue::GetInstanceByPath
  2823. //
  2824. // Static entry point for providers to obtain a single empty instance
  2825. // of a provider object.
  2826. //
  2827. // Inputs: LPCWSTR pszInstancePath - Path to Object. This
  2828. // MUST be a full path,
  2829. // MethodContext *pMethodContext - Method Context containing
  2830. // (hopefully) the WbemContext we need
  2831. // to propogate.
  2832. //
  2833. // Outputs: CInstance** ppInstance - Pointer to store new
  2834. // pInstance in. Must be Released by
  2835. // caller.
  2836. //
  2837. // Returns: HRESULT hr - Status code.
  2838. //
  2839. // Comments: This is an internal entry point, allowing providers
  2840. // to short circuit having to go through WBEM to access
  2841. // data from other providers.
  2842. //
  2843. /////////////////////////////////////////////////////////////////////
  2844. HRESULT WINAPI CWbemProviderGlue::GetInstanceByPath(
  2845. LPCWSTR pszInstancePath,
  2846. CInstance **ppInstance,
  2847. MethodContext *pMethodContext /* = NULL */
  2848. )
  2849. {
  2850. PROVIDER_INSTRUMENTATION_START(pMethodContext, StopWatch::FrameworkTimer);
  2851. HRESULT hr = WBEM_E_FAILED;
  2852. if ( (pszInstancePath != NULL) &&
  2853. (ppInstance != NULL) )
  2854. {
  2855. CHString strComputerName;
  2856. GetComputerName( strComputerName );
  2857. // For this revision, we DO NOT support getting paths that are not local.
  2858. // This is because if the machine name is anything other than the local
  2859. // one, we run the risk of freezing while CIMOM goes out and tries to find
  2860. // the machine (up to around 5 minutes according to his Levness.
  2861. ParsedObjectPath *pParsedPath = NULL;
  2862. CObjectPathParser objpathParser;
  2863. // Parse the object path passed to us by CIMOM
  2864. // ==========================================
  2865. int nStatus = objpathParser.Parse( pszInstancePath, &pParsedPath );
  2866. try
  2867. {
  2868. if ( 0 == nStatus )
  2869. {
  2870. // Machine names MUST match. Null indicates no machine name specified.
  2871. if (( pParsedPath->m_pServer == NULL) ||
  2872. ( strComputerName.CompareNoCase( pParsedPath->m_pServer ) == 0 ) ||
  2873. ( wcscmp(pParsedPath->m_pServer, L".") == 0 )
  2874. )
  2875. {
  2876. // Now try to find the provider based on the class name
  2877. CHString strNamespace;
  2878. // Pull out the name space parts, and concatenate them using a '\\'
  2879. // character. e.g. root\default.
  2880. for ( DWORD dwCtr = 0; dwCtr < pParsedPath->m_dwNumNamespaces; dwCtr++ )
  2881. {
  2882. if ( dwCtr != 0 )
  2883. {
  2884. strNamespace += L"\\";
  2885. }
  2886. strNamespace += pParsedPath->m_paNamespaces[dwCtr];
  2887. }
  2888. // We need to propogate the Wbem Context if we are going out
  2889. // to CIMOM!
  2890. IWbemContextPtr pWbemContext;
  2891. CWbemProviderGlue *pGlue = NULL;
  2892. if ( NULL != pMethodContext )
  2893. {
  2894. pWbemContext.Attach(pMethodContext->GetIWBEMContext());
  2895. pGlue = pMethodContext->GetProviderGlue();
  2896. }
  2897. else
  2898. {
  2899. ASSERT_BREAK(DEPRECATED);
  2900. }
  2901. InternalMethodContextPtr pInternalContext (
  2902. new InternalMethodContext(
  2903. NULL,
  2904. pWbemContext,
  2905. pGlue), false);
  2906. if ( NULL != pInternalContext )
  2907. {
  2908. hr = GetInstanceFromCIMOM( pszInstancePath, strNamespace, pInternalContext, ppInstance );
  2909. }
  2910. else
  2911. {
  2912. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  2913. }
  2914. } // IF Machine Names MATCH
  2915. else
  2916. {
  2917. hr = WBEM_E_INVALID_PARAMETER; // INVALID MACHINE NAME
  2918. }
  2919. // Clean up the Parsed Path
  2920. objpathParser.Free( pParsedPath );
  2921. } // IF nStatus == 0
  2922. else
  2923. {
  2924. hr = WBEM_E_INVALID_OBJECT_PATH;
  2925. }
  2926. }
  2927. catch ( ... )
  2928. {
  2929. // Clean up the Parsed Path
  2930. if (pParsedPath)
  2931. {
  2932. objpathParser.Free( pParsedPath );
  2933. }
  2934. throw ;
  2935. }
  2936. }
  2937. else
  2938. {
  2939. hr = WBEM_E_INVALID_PARAMETER;
  2940. LogErrorMessage(L"NULL parameter to GetInstanceByPath");
  2941. ASSERT_BREAK(WBEM_E_INVALID_PARAMETER);
  2942. }
  2943. PROVIDER_INSTRUMENTATION_START(pMethodContext, StopWatch::ProviderTimer);
  2944. return hr;
  2945. }
  2946. /////////////////////////////////////////////////////////////////////
  2947. //
  2948. // Function: CWbemProviderGlue::GetInstanceFromCIMOM
  2949. //
  2950. // Static entry point for providers to obtain a single instance
  2951. // of a WBEM Object. obtaining said object from CIMOM.
  2952. //
  2953. // Inputs: LPCWSTR pszInstancePath - Path to Object. This
  2954. // MUST be a full path,
  2955. // LPCWSTR pszNameSpace - NameSpace of Object.
  2956. // MethodContext *pMethodContext - Method Context
  2957. //
  2958. // Outputs: CInstance **ppInstance - Pointer to store new
  2959. // pInstance in. Must be Released by
  2960. // caller.
  2961. //
  2962. // Returns: HRESULT hr - Status code.
  2963. // will return WBEM_E_INVALID_NAMESPACE if it's not a namespace we support
  2964. // (might otherwise be valid, but not so far as WE are concerned).
  2965. //
  2966. // Comments: This is an internal entry point, allowing providers
  2967. // that failed the short circuit to be propogated
  2968. // by calling into CIMOM.
  2969. //
  2970. /////////////////////////////////////////////////////////////////////
  2971. HRESULT WINAPI CWbemProviderGlue::GetInstanceFromCIMOM(
  2972. LPCWSTR pszInstancePath,
  2973. LPCWSTR pszNamespace,
  2974. MethodContext *pMethodContext,
  2975. CInstance **ppInstance
  2976. )
  2977. {
  2978. PROVIDER_INSTRUMENTATION_START(pMethodContext, StopWatch::FrameworkTimer);
  2979. HRESULT hr = WBEM_E_FAILED;
  2980. if (IsVerboseLoggingEnabled())
  2981. {
  2982. LogMessage3(L"%s (%s)", IDS_INSTANCEFROMCIMOM, pszInstancePath);
  2983. }
  2984. // We need to propogate the Wbem Context (if any) that was passed to
  2985. // us by CIMOM.
  2986. IWbemContextPtr pWbemContext;
  2987. if ( NULL != pMethodContext )
  2988. {
  2989. pWbemContext.Attach(pMethodContext->GetIWBEMContext());
  2990. }
  2991. else
  2992. {
  2993. ASSERT_BREAK(DEPRECATED);
  2994. }
  2995. // If we failed to find the provider, try using CIMOM to do our
  2996. // dirty work for us.
  2997. IWbemServicesPtr piService;
  2998. IWbemClassObjectPtr piObject;
  2999. // get a service interface
  3000. if ( (pszNamespace == NULL) || (pszNamespace[0] == L'\0' ))
  3001. {
  3002. piService.Attach(GetNamespaceConnection(NULL, pMethodContext));
  3003. }
  3004. else
  3005. {
  3006. piService.Attach(GetNamespaceConnection( pszNamespace, pMethodContext ));
  3007. }
  3008. if ( NULL != piService )
  3009. {
  3010. // No go out to CIMOM to get the object, if this succeeds, new an
  3011. // instance and store everything internally.
  3012. {
  3013. // Assures that impersonation goes
  3014. // back to the way it was before the
  3015. // call to CIMOM.
  3016. CAutoImpRevert air;
  3017. DWORD dwImpErr = air.LastError();
  3018. if(dwImpErr == ERROR_SUCCESS)
  3019. {
  3020. PROVIDER_INSTRUMENTATION_START(pMethodContext, StopWatch::WinMgmtTimer);
  3021. hr = piService->GetObject( bstr_t(pszInstancePath), 0, pWbemContext, &piObject, NULL );
  3022. PROVIDER_INSTRUMENTATION_START(pMethodContext, StopWatch::FrameworkTimer);
  3023. }
  3024. else
  3025. {
  3026. LogErrorMessage2(L"Failed to open current thread token for checking impersonation, with error %d", dwImpErr);
  3027. hr = WBEM_E_FAILED;
  3028. }
  3029. }
  3030. if ( SUCCEEDED(hr) )
  3031. {
  3032. *ppInstance = new CInstance( piObject, pMethodContext );
  3033. if (*ppInstance == NULL)
  3034. {
  3035. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  3036. }
  3037. }
  3038. }
  3039. else
  3040. {
  3041. LogErrorMessage(IDS_FAILED);
  3042. hr = WBEM_E_INVALID_NAMESPACE;
  3043. }
  3044. if (IsVerboseLoggingEnabled())
  3045. {
  3046. if (SUCCEEDED(hr))
  3047. {
  3048. LogMessage3(L"%s (%s) - Succeeded", IDS_INSTANCEFROMCIMOM, pszInstancePath);
  3049. }
  3050. else
  3051. {
  3052. LogMessage4(L"%s (%s) - FAILED (%x)", IDS_INSTANCEFROMCIMOM, pszInstancePath, hr);
  3053. }
  3054. }
  3055. PROVIDER_INSTRUMENTATION_START(pMethodContext, StopWatch::ProviderTimer);
  3056. return hr;
  3057. }
  3058. /////////////////////////////////////////////////////////////////////
  3059. //
  3060. // Function: CWbemProviderGlue::SearchMapForProvider
  3061. //
  3062. // Searches our Provider map for a match against the supplied
  3063. // provider name/NameSpace combination
  3064. //
  3065. // Inputs: const LPCWSTR& strName - Provider Name to find.
  3066. // const LPCWSTR& strNamespace - Provider's Namespace
  3067. //
  3068. // Outputs: None.
  3069. //
  3070. // Returns: Provider *pointer to a provider that was given to
  3071. // us by a call to FrameworkLogin.
  3072. //
  3073. // Comments: None.
  3074. //
  3075. //
  3076. /////////////////////////////////////////////////////////////////////
  3077. Provider *CWbemProviderGlue::SearchMapForProvider(
  3078. LPCWSTR a_pszProviderName,
  3079. LPCWSTR a_pszNamespace
  3080. )
  3081. {
  3082. Provider *pProvider = NULL;
  3083. STRING2LPVOID::iterator mapIter;
  3084. // If our NameSpace is non-NULL (we use DEFAULT_NAMEPSACE then), AND it
  3085. // is not DEFAULT_NAMESPACE, concat the namespace to the provider name
  3086. // so we can differentiate providers across namespaces.
  3087. CHString strQualifiedName( a_pszProviderName );
  3088. CHString strLocNamespace( a_pszNamespace );
  3089. if ( !strLocNamespace.IsEmpty()
  3090. && 0 != strLocNamespace.CompareNoCase( DEFAULT_NAMESPACE ) )
  3091. {
  3092. // Convert the / characters to \ for comparison
  3093. WCHAR *pszBuff;
  3094. pszBuff = strLocNamespace.GetBuffer(0);
  3095. while ((pszBuff = wcschr(pszBuff, '/')) != NULL)
  3096. {
  3097. *pszBuff = '\\';
  3098. }
  3099. strLocNamespace.ReleaseBuffer();
  3100. strQualifiedName += strLocNamespace;
  3101. }
  3102. // Convert characters to upper case before searching for
  3103. // them in the map. Since we convert to upper case when
  3104. // we store the map associations, this effectively makes
  3105. // us case-insensitive.
  3106. strQualifiedName.MakeUpper();
  3107. // Protect the map while we're inside this
  3108. LockProviderMap();
  3109. try
  3110. {
  3111. if( ( mapIter = s_providersmap.find( strQualifiedName ) ) != s_providersmap.end() )
  3112. {
  3113. pProvider = (Provider*) (*mapIter).second;
  3114. }
  3115. }
  3116. catch ( ... )
  3117. {
  3118. UnlockProviderMap();
  3119. throw;
  3120. }
  3121. UnlockProviderMap();
  3122. return pProvider;
  3123. }
  3124. /////////////////////////////////////////////////////////////////////
  3125. //
  3126. // Function: CWbemProviderGlue::AddProviderToMap
  3127. //
  3128. // Adds a provider to our map. Searches the map first, and if it's
  3129. // not in it, adds it to the map.
  3130. //
  3131. // Inputs: const LPCWSTR strName - Provider Name to Add.
  3132. // const LPCWSTR strNamespace - Namespace for provider.
  3133. // Provider *pProvider - Provider to add to map.
  3134. //
  3135. // Outputs: None.
  3136. //
  3137. // Returns: Provider *pointer to a provider in the map (may
  3138. // be different from the supplied one)
  3139. //
  3140. // Comments: None.
  3141. //
  3142. //
  3143. /////////////////////////////////////////////////////////////////////
  3144. Provider *CWbemProviderGlue::AddProviderToMap(
  3145. LPCWSTR a_szProviderName,
  3146. LPCWSTR a_pszNamespace,
  3147. Provider *a_pProvider
  3148. )
  3149. {
  3150. STRING2LPVOID::iterator mapIter;
  3151. // If our NameSpace is non-NULL (we use DEFAULT_NAMEPSACE then), AND it
  3152. // is not DEFAULT_NAMESPACE, concat the namespace to the provider name
  3153. // so we can differentiate providers across namespaces.
  3154. CHString strQualifiedName( a_szProviderName );
  3155. if ( ( a_pszNamespace != NULL) && (a_pszNamespace[0] != L'\0')
  3156. && (0 != _wcsicmp(a_pszNamespace, DEFAULT_NAMESPACE )) )
  3157. {
  3158. strQualifiedName += a_pszNamespace;
  3159. }
  3160. // Convert characters to upper case before searching for
  3161. // them in the map. Since we convert to upper case when
  3162. // we store the map associations, this effectively makes
  3163. // us case-insensitive.
  3164. strQualifiedName.MakeUpper();
  3165. // Protect the map while we're inside this
  3166. Provider *pReturnProvider = NULL;
  3167. LockProviderMap();
  3168. try
  3169. {
  3170. // First check if we've already got a provider.
  3171. if( ( mapIter = s_providersmap.find( strQualifiedName ) ) != s_providersmap.end() )
  3172. {
  3173. pReturnProvider = (Provider*) (*mapIter).second;
  3174. //delete it, we're gonna update it shortly
  3175. s_providersmap.erase(mapIter);
  3176. }
  3177. if ( NULL == pReturnProvider )
  3178. {
  3179. pReturnProvider = a_pProvider;
  3180. }
  3181. //add in the newly logged in provider
  3182. s_providersmap[strQualifiedName] = (LPVOID) a_pProvider;
  3183. }
  3184. catch ( ... )
  3185. {
  3186. UnlockProviderMap();
  3187. throw;
  3188. }
  3189. UnlockProviderMap();
  3190. return pReturnProvider;
  3191. }
  3192. void CWbemProviderGlue::GetComputerName( CHString& strComputerName )
  3193. {
  3194. // Fill the supplied CHString with the local machine name
  3195. DWORD dwBufferLength = MAX_COMPUTERNAME_LENGTH + 1;
  3196. FRGetComputerName(strComputerName.GetBuffer( dwBufferLength ), &dwBufferLength);
  3197. strComputerName.ReleaseBuffer();
  3198. if (strComputerName.IsEmpty())
  3199. {
  3200. strComputerName = L"DEFAULT";
  3201. }
  3202. }
  3203. BOOL CWbemProviderGlue::FrameworkLoginDLL(LPCWSTR a_pszName)
  3204. {
  3205. return CWbemProviderGlue::FrameworkLoginDLL(a_pszName, NULL);
  3206. }
  3207. BOOL CWbemProviderGlue::FrameworkLogoffDLL(LPCWSTR a_pszNname)
  3208. {
  3209. return CWbemProviderGlue::FrameworkLogoffDLL(a_pszNname, NULL);
  3210. }
  3211. void CWbemProviderGlue::IncrementObjectCount(void)
  3212. {
  3213. InterlockedIncrement(&s_lObjects);
  3214. if (IsVerboseLoggingEnabled())
  3215. {
  3216. LogMessage2(L"CWbemProviderGlue::IncrementObjectCount. Count is (approx) %d", s_lObjects);
  3217. }
  3218. }
  3219. LONG CWbemProviderGlue::DecrementObjectCount(void)
  3220. {
  3221. LONG lRet = InterlockedDecrement(&s_lObjects);
  3222. if (IsVerboseLoggingEnabled())
  3223. {
  3224. LogMessage2(L"CWbemProviderGlue::DecrementObjectCount. Count is (approx) %d", s_lObjects);
  3225. }
  3226. return lRet;
  3227. }
  3228. // checks impersonation level
  3229. // impersonates client if allowed
  3230. HRESULT WINAPI CWbemProviderGlue::CheckImpersonationLevel()
  3231. {
  3232. HRESULT hr = WBEM_E_ACCESS_DENIED;
  3233. if (CWbemProviderGlue::GetPlatform() == VER_PLATFORM_WIN32_NT)
  3234. {
  3235. HRESULT hRes = WbemCoImpersonateClient();
  3236. if (SUCCEEDED(hRes)) // From cominit.cpp - needed for nt3.51
  3237. {
  3238. // Now, let's check the impersonation level. First, get the thread token
  3239. HANDLE hThreadTok;
  3240. DWORD dwImp, dwBytesReturned;
  3241. if (!OpenThreadToken(
  3242. GetCurrentThread(),
  3243. TOKEN_QUERY,
  3244. TRUE,
  3245. &hThreadTok
  3246. ))
  3247. {
  3248. DWORD dwLastError = GetLastError();
  3249. if (dwLastError == ERROR_NO_TOKEN)
  3250. {
  3251. // If the CoImpersonate works, but the OpenThreadToken fails due to ERROR_NO_TOKEN, we
  3252. // are running under the process token (either local system, or if we are running
  3253. // with /exe, the rights of the logged in user). In either case, impersonation rights
  3254. // don't apply. We have the full rights of that user.
  3255. hr = WBEM_S_NO_ERROR;
  3256. }
  3257. else
  3258. {
  3259. // If we failed to get the thread token for any other reason, log an error.
  3260. LogErrorMessage2(L"Impersonation failure - OpenThreadToken failed (0x%x)", dwLastError);
  3261. hr = WBEM_E_ACCESS_DENIED;
  3262. }
  3263. }
  3264. else
  3265. {
  3266. // We really do have a thread token, so let's retrieve its level
  3267. if (GetTokenInformation(
  3268. hThreadTok,
  3269. TokenImpersonationLevel,
  3270. &dwImp,
  3271. sizeof(DWORD),
  3272. &dwBytesReturned
  3273. ))
  3274. {
  3275. // Is the impersonation level Impersonate?
  3276. if ((dwImp == SecurityImpersonation) || (dwImp == SecurityDelegation))
  3277. {
  3278. hr = WBEM_S_NO_ERROR;
  3279. }
  3280. else
  3281. {
  3282. hr = WBEM_E_ACCESS_DENIED;
  3283. LogErrorMessage3(L"%s Level(%d)", IDS_ImpersonationFailed, dwImp);
  3284. }
  3285. }
  3286. else
  3287. {
  3288. hr = WBEM_E_FAILED;
  3289. LogErrorMessage3(L"%s Token(%d)", IDS_ImpersonationFailed, GetLastError());
  3290. }
  3291. // Done with this handle
  3292. CloseHandle(hThreadTok);
  3293. }
  3294. if (FAILED(hr))
  3295. {
  3296. WbemCoRevertToSelf();
  3297. }
  3298. }
  3299. else if (hRes == E_NOTIMPL)
  3300. {
  3301. // On 3.51 or vanilla 95, this call is not implemented, we should work anyway
  3302. hr = WBEM_S_NO_ERROR;
  3303. }
  3304. else
  3305. {
  3306. LogErrorMessage3(L"%s CoImpersonate(%d)", IDS_ImpersonationFailed, hRes);
  3307. }
  3308. }
  3309. else
  3310. {
  3311. // let win9X in...
  3312. hr = WBEM_S_NO_ERROR;
  3313. }
  3314. if (IsVerboseLoggingEnabled())
  3315. {
  3316. WCHAR wszName[UNLEN + DNLEN + 1 + 1]; // domain + \ + name + null
  3317. DWORD dwLen = UNLEN + DNLEN + 1 + 1;
  3318. if (GetUserNameEx(NameSamCompatible, wszName, &dwLen))
  3319. {
  3320. LogMessage2(L"Impersonation running as: %s", wszName);
  3321. }
  3322. }
  3323. return hr;
  3324. }
  3325. /////////////////////////////////////////////////////////////////////
  3326. //
  3327. // Function: CWbemProviderGlue::GetInstancesByQueryAsynch
  3328. //
  3329. // Static entry point for providers to obtain instances from
  3330. // other providers. Note that this is not, strictly speaking,
  3331. // an asynchronous implementation - it does HELP the asynch calls
  3332. // in that it does not build a big list and that the callback allows
  3333. // the provider to respond asynchronously
  3334. //
  3335. // Inputs: LPCWSTR Query to execute "Select * from win32_foo where bar = "baz""
  3336. // Provider * this is the "this" pointer for the requester
  3337. // LPProviderInstanceCallback callback function to eat the instances provided
  3338. // LPCWSTR pszNamespace - Namespace of provider.
  3339. //
  3340. // Outputs: None.
  3341. //
  3342. // Returns: HRESULT hr - Status code.
  3343. //
  3344. //
  3345. /////////////////////////////////////////////////////////////////////
  3346. HRESULT WINAPI CWbemProviderGlue::GetInstancesByQueryAsynch(
  3347. LPCWSTR query,
  3348. Provider *pRequester,
  3349. LPProviderInstanceCallback pCallback,
  3350. LPCWSTR pszNamespace,
  3351. MethodContext *pMethodContext,
  3352. void *pUserData
  3353. )
  3354. {
  3355. PROVIDER_INSTRUMENTATION_START(pMethodContext, StopWatch::FrameworkTimer);
  3356. if (IsVerboseLoggingEnabled())
  3357. {
  3358. LogMessage2(L"GetInstancesByQueryAsynch (%s)", query);
  3359. }
  3360. HRESULT hr = WBEM_E_FAILED;
  3361. if ( (query != NULL) &&
  3362. (pRequester != NULL) &&
  3363. (pCallback != NULL) &&
  3364. (pMethodContext != NULL) )
  3365. {
  3366. // We need to propogate the WBEM context...ESPECIALLY...if we are going out
  3367. // to CIMOM.
  3368. IWbemContextPtr pWbemContext;
  3369. if (pMethodContext)
  3370. {
  3371. pWbemContext.Attach(pMethodContext->GetIWBEMContext());
  3372. }
  3373. else
  3374. {
  3375. ASSERT_BREAK(DEPRECATED);
  3376. }
  3377. // Now create an Internal Method Context object, since this function
  3378. // only gets called internal to our DLLs
  3379. InternalMethodContextAsynchPtr pInternalContext (new InternalMethodContextAsynch(pRequester,
  3380. pCallback,
  3381. pWbemContext,
  3382. pMethodContext,
  3383. pUserData), false);
  3384. if ( NULL != pInternalContext )
  3385. {
  3386. // using CIMOM to do our dirty work for us.
  3387. IWbemServicesPtr piService;
  3388. // get a service interface
  3389. if (pszNamespace == NULL || pszNamespace[0] == L'\0')
  3390. {
  3391. piService.Attach(GetNamespaceConnection(NULL, pMethodContext));
  3392. }
  3393. else
  3394. {
  3395. piService.Attach(GetNamespaceConnection( pszNamespace, pMethodContext ));
  3396. }
  3397. if ( NULL != piService )
  3398. {
  3399. IEnumWbemClassObjectPtr pEnum;
  3400. {
  3401. // Assures that impersonation goes
  3402. // back to the way it was before the
  3403. // call to CIMOM.
  3404. CAutoImpRevert air;
  3405. DWORD dwImpErr = air.LastError();
  3406. if(dwImpErr == ERROR_SUCCESS)
  3407. {
  3408. PROVIDER_INSTRUMENTATION_START(pMethodContext, StopWatch::WinMgmtTimer);
  3409. hr = piService->ExecQuery(bstr_t(IDS_WQL),
  3410. bstr_t(query),
  3411. WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
  3412. pWbemContext,
  3413. &pEnum);
  3414. PROVIDER_INSTRUMENTATION_START(pMethodContext, StopWatch::FrameworkTimer);
  3415. }
  3416. else
  3417. {
  3418. LogErrorMessage2(L"Failed to open current thread token for checking impersonation, with error %d", dwImpErr);
  3419. hr = WBEM_E_FAILED;
  3420. }
  3421. }
  3422. if ( SUCCEEDED( hr ) )
  3423. {
  3424. IWbemClassObjectPtr pObj;
  3425. ULONG nReturned;
  3426. // we retrieve all instances of this class and it's children. Note that
  3427. // the next returns WBEM_S_FALSE at the end which PASSES the SUCCEEDED()
  3428. // test, but fails the pObj test.
  3429. PROVIDER_INSTRUMENTATION_START(pMethodContext, StopWatch::WinMgmtTimer);
  3430. while (SUCCEEDED(hr) && SUCCEEDED(hr = pEnum->Next(GLUETIMEOUT, 1, &pObj, &nReturned)) && (pObj != NULL))
  3431. {
  3432. PROVIDER_INSTRUMENTATION_START(pMethodContext, StopWatch::FrameworkTimer);
  3433. CInstancePtr pInstance(new CInstance(pObj, pMethodContext), false);
  3434. if (pInstance != NULL)
  3435. {
  3436. // For reasons quite beyond me, InternalContext::Commit doesn't
  3437. // release, but external does. Note that the smartptr is doing
  3438. // the release here.
  3439. hr = pInternalContext->Commit(pInstance);
  3440. }
  3441. else
  3442. {
  3443. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  3444. }
  3445. }
  3446. PROVIDER_INSTRUMENTATION_START(pMethodContext, StopWatch::FrameworkTimer);
  3447. // the Next will return WBEM_S_FALSE when it is done. However, that
  3448. // means that THIS function had no error.
  3449. if (hr == WBEM_S_FALSE)
  3450. {
  3451. hr = WBEM_S_NO_ERROR;
  3452. }
  3453. } // IF SUCCEEDED
  3454. }
  3455. else
  3456. {
  3457. LogErrorMessage(IDS_FAILED);
  3458. }
  3459. }
  3460. else
  3461. {
  3462. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  3463. }
  3464. }
  3465. else
  3466. {
  3467. hr = WBEM_E_INVALID_PARAMETER;
  3468. LogErrorMessage(L"NULL parameter to GetInstancesByQueryAsynch");
  3469. ASSERT_BREAK(WBEM_E_INVALID_PARAMETER);
  3470. }
  3471. if (IsVerboseLoggingEnabled())
  3472. {
  3473. if (SUCCEEDED(hr))
  3474. {
  3475. LogMessage2(L"GetInstancesByQueryAsynch (%s) - Succeeded", query);
  3476. }
  3477. else
  3478. {
  3479. LogMessage3(L"GetInstancesByQueryAsynch (%s) - FAILED (%x)", query, hr);
  3480. }
  3481. }
  3482. PROVIDER_INSTRUMENTATION_START(pMethodContext, StopWatch::ProviderTimer);
  3483. return hr;
  3484. }
  3485. IWbemServices *CWbemProviderGlue::InternalGetNamespaceConnection(
  3486. LPCWSTR pwszNameSpace
  3487. )
  3488. {
  3489. IWbemServices *pWbemServices = NULL;
  3490. bstr_t bstrNamespace;
  3491. // Root\CimV2 is the default name space
  3492. if ( NULL != pwszNameSpace && L'\0' != *pwszNameSpace )
  3493. {
  3494. bstrNamespace = pwszNameSpace;
  3495. }
  3496. else
  3497. {
  3498. ASSERT_BREAK(DEPRECATED);
  3499. bstrNamespace = DEFAULT_NAMESPACE;
  3500. }
  3501. if (IsVerboseLoggingEnabled())
  3502. {
  3503. LogMessage3(L"%s%s", IDS_GETNAMESPACECONNECTION, (LPCWSTR)bstrNamespace);
  3504. }
  3505. _wcsupr(bstrNamespace);
  3506. // If we are looking for the namespace our class is in, we already
  3507. // got an IWbemServices pointer for this from Initialize
  3508. if (m_strNamespace.Compare(bstrNamespace) == 0)
  3509. {
  3510. pWbemServices = m_pServices;
  3511. pWbemServices->AddRef();
  3512. }
  3513. else
  3514. {
  3515. IWbemLocatorPtr pIWbemLocator;
  3516. HRESULT hRes = CoCreateInstance (
  3517. CLSID_WbemLocator, //CLSID_WbemAdministrativeLocator,
  3518. NULL,
  3519. CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
  3520. IID_IUnknown,
  3521. ( void ** ) &pIWbemLocator
  3522. ) ;
  3523. if (SUCCEEDED(hRes))
  3524. {
  3525. hRes = pIWbemLocator->ConnectServer(bstrNamespace, // Namespace
  3526. NULL, // Userid
  3527. NULL, // PW
  3528. NULL, // Locale
  3529. 0, // flags
  3530. NULL, // Authority
  3531. NULL, // Context
  3532. &pWbemServices
  3533. );
  3534. if (FAILED(hRes))
  3535. {
  3536. LogErrorMessage3(L"Failed to Connectserver to namespace %s (%x)",
  3537. (LPCWSTR)bstrNamespace, hRes);
  3538. }
  3539. }
  3540. else
  3541. {
  3542. LogErrorMessage2(L"Failed to get locator (%x)", hRes);
  3543. }
  3544. }
  3545. return pWbemServices;
  3546. }
  3547. IWbemServices *WINAPI CWbemProviderGlue::GetNamespaceConnection( LPCWSTR wszNameSpace, MethodContext *pMethodContext )
  3548. {
  3549. IWbemServices *pServices = NULL;
  3550. CWbemProviderGlue *pGlue = NULL;
  3551. if ( pMethodContext && (pGlue = pMethodContext->GetProviderGlue()) )
  3552. {
  3553. pServices = pGlue->InternalGetNamespaceConnection(wszNameSpace);
  3554. }
  3555. else
  3556. {
  3557. pServices = GetNamespaceConnection(wszNameSpace);
  3558. }
  3559. return pServices;
  3560. }
  3561. /////////////////////////////////////////////////////////////////////
  3562. //
  3563. // Function: CWbemProviderGlue::FrameworkLoginDLL
  3564. //
  3565. // Static entry point for providers to register their DLL with
  3566. // the framework. This PLONG must be the same one used in
  3567. // FrameworkLogoffDll and as the parameter to the CWbemGlueFactory
  3568. // constructor.
  3569. //
  3570. /////////////////////////////////////////////////////////////////////
  3571. BOOL CWbemProviderGlue::FrameworkLoginDLL(LPCWSTR pszName, PLONG plRefCount)
  3572. {
  3573. BOOL bRet = TRUE;
  3574. LogMessage3(L"%s%s", IDS_DLLLOGGED, pszName);
  3575. // If this *is* null, that means we are using the backword compatibility
  3576. // version of FrameworkLoginDLL, which uses CWbemProviderGlue::s_lObjects
  3577. // which has already been initialized.
  3578. if (plRefCount != NULL)
  3579. {
  3580. *plRefCount = 0;
  3581. }
  3582. return bRet;
  3583. }
  3584. /////////////////////////////////////////////////////////////////////
  3585. //
  3586. // Function: CWbemProviderGlue::FrameworkLogoffDLL
  3587. //
  3588. // Static entry point for providers to determine whether they
  3589. // should return TRUE to DllCanUnloadNow. This PLONG must be the
  3590. // same one used in FrameworkLoginDLL and as the parameter to the
  3591. // CWbemGlueFactory constructor.
  3592. //
  3593. /////////////////////////////////////////////////////////////////////
  3594. BOOL CWbemProviderGlue::FrameworkLogoffDLL(LPCWSTR pszName, PLONG plRefCount)
  3595. {
  3596. BOOL bRet = TRUE;
  3597. LogMessage3(L"%s%s", IDS_DLLUNLOGGED, pszName);
  3598. // If this *is* null, that means we are using the backword compatibility
  3599. // version of FrameworkLoginDLL
  3600. if (plRefCount != NULL)
  3601. {
  3602. bRet = *plRefCount == 0;
  3603. }
  3604. else
  3605. {
  3606. bRet = CWbemProviderGlue::s_lObjects == 0;
  3607. }
  3608. return bRet;
  3609. }
  3610. /////////////////////////////////////////////////////////////////////
  3611. //
  3612. // Function: CWbemProviderGlue::AddToFactoryMap
  3613. //
  3614. // Adds a new CWbemGlueFactory to the s_factorymap map.
  3615. //
  3616. /////////////////////////////////////////////////////////////////////
  3617. VOID CWbemProviderGlue::AddToFactoryMap(const CWbemGlueFactory *pGlue, PLONG plRefCount)
  3618. {
  3619. LockFactoryMap();
  3620. try
  3621. {
  3622. // If this *is* null, that means we are using the backword compatibility
  3623. // version of FrameworkLoginDLL
  3624. if (plRefCount != NULL)
  3625. {
  3626. CWbemProviderGlue::s_factorymap[pGlue] = plRefCount;
  3627. }
  3628. else
  3629. {
  3630. CWbemProviderGlue::s_factorymap[pGlue] = &CWbemProviderGlue::s_lObjects;
  3631. }
  3632. }
  3633. catch (...)
  3634. {
  3635. UnlockFactoryMap();
  3636. throw;
  3637. }
  3638. UnlockFactoryMap();
  3639. }
  3640. /////////////////////////////////////////////////////////////////////
  3641. //
  3642. // Function: CWbemProviderGlue::RemoveFromFactoryMap
  3643. //
  3644. // Removes a CWbemGlueFactory from the s_factorymap map.
  3645. //
  3646. /////////////////////////////////////////////////////////////////////
  3647. VOID CWbemProviderGlue::RemoveFromFactoryMap(const CWbemGlueFactory *pGlue)
  3648. {
  3649. LockFactoryMap();
  3650. try
  3651. {
  3652. bool bFound = false;
  3653. PTR2PLONG::iterator mapIter;
  3654. mapIter = s_factorymap.find(pGlue);
  3655. if ( mapIter != s_factorymap.end() )
  3656. {
  3657. s_factorymap.erase(mapIter);
  3658. }
  3659. else
  3660. {
  3661. LogErrorMessage2(L"Can't find factory in map: %p", pGlue);
  3662. }
  3663. }
  3664. catch( ... )
  3665. {
  3666. UnlockFactoryMap();
  3667. throw;
  3668. }
  3669. UnlockFactoryMap();
  3670. }
  3671. /////////////////////////////////////////////////////////////////////
  3672. //
  3673. // Function: CWbemProviderGlue::IncrementMapCount
  3674. //
  3675. // Increments the refcount on a DLL
  3676. //
  3677. /////////////////////////////////////////////////////////////////////
  3678. LONG CWbemProviderGlue::IncrementMapCount(const CWbemGlueFactory *pGlue)
  3679. {
  3680. LONG lRet = -1;
  3681. LockFactoryMap();
  3682. try
  3683. {
  3684. PTR2PLONG::iterator mapIter;
  3685. mapIter = CWbemProviderGlue::s_factorymap.find( pGlue );
  3686. if (mapIter != CWbemProviderGlue::s_factorymap.end())
  3687. {
  3688. lRet = InterlockedIncrement((*mapIter).second);
  3689. }
  3690. else
  3691. {
  3692. // This is very bad. This should have been created
  3693. // at CWbemGlueFactory constructor time.
  3694. LogErrorMessage2(L"Can't find factory in map: %p", pGlue);
  3695. }
  3696. }
  3697. catch( ... )
  3698. {
  3699. UnlockFactoryMap();
  3700. throw;
  3701. }
  3702. UnlockFactoryMap();
  3703. return lRet;
  3704. }
  3705. /////////////////////////////////////////////////////////////////////
  3706. //
  3707. // Function: CWbemProviderGlue::IncrementMapCount
  3708. //
  3709. // Increments the refcount on a DLL
  3710. //
  3711. /////////////////////////////////////////////////////////////////////
  3712. LONG CWbemProviderGlue::IncrementMapCount(PLONG pCount)
  3713. {
  3714. return InterlockedIncrement(pCount);
  3715. }
  3716. /////////////////////////////////////////////////////////////////////
  3717. //
  3718. // Function: CWbemProviderGlue::DecrementMapCount
  3719. //
  3720. // Decrements the refcount on a DLL
  3721. //
  3722. /////////////////////////////////////////////////////////////////////
  3723. LONG CWbemProviderGlue::DecrementMapCount(const CWbemGlueFactory *pGlue)
  3724. {
  3725. LONG lRet = -1;
  3726. LockFactoryMap();
  3727. try
  3728. {
  3729. // Find the matching CWbemGlueFactory in the CWbemGlueFactory<->refcount map
  3730. PTR2PLONG::iterator mapIter;
  3731. mapIter = CWbemProviderGlue::s_factorymap.find( pGlue );
  3732. if (mapIter != CWbemProviderGlue::s_factorymap.end())
  3733. {
  3734. lRet = InterlockedDecrement((*mapIter).second);
  3735. if (lRet < 0)
  3736. {
  3737. LogErrorMessage2(L"RefCount < 0 for glue %p", pGlue);
  3738. ASSERT_BREAK(DUPLICATE_RELEASE);
  3739. }
  3740. }
  3741. else
  3742. {
  3743. LogErrorMessage2(L"Can't find factory in map: %p", pGlue);
  3744. }
  3745. }
  3746. catch ( ... )
  3747. {
  3748. UnlockFactoryMap();
  3749. throw;
  3750. }
  3751. UnlockFactoryMap();
  3752. return lRet;
  3753. }
  3754. /////////////////////////////////////////////////////////////////////
  3755. //
  3756. // Function: CWbemProviderGlue::DecrementMapCount
  3757. //
  3758. // Decrements the refcount on a DLL
  3759. //
  3760. /////////////////////////////////////////////////////////////////////
  3761. LONG CWbemProviderGlue::DecrementMapCount(PLONG pCount)
  3762. {
  3763. LONG lRet = InterlockedDecrement(pCount);
  3764. if (lRet < 0)
  3765. {
  3766. LogErrorMessage2(L"RefCount < 0 for %p", pCount);
  3767. ASSERT_BREAK(DUPLICATE_RELEASE);
  3768. }
  3769. return lRet;
  3770. }
  3771. /////////////////////////////////////////////////////////////////////
  3772. //
  3773. // Function: CWbemProviderGlue::GetMapCountPtr
  3774. //
  3775. // Returns the pointer to the plong for this glue factory
  3776. //
  3777. /////////////////////////////////////////////////////////////////////
  3778. PLONG CWbemProviderGlue::GetMapCountPtr(const CWbemGlueFactory *pGlue)
  3779. {
  3780. PLONG pRet = NULL;
  3781. LockFactoryMap();
  3782. try
  3783. {
  3784. // Find the matching CWbemGlueFactory in the CWbemGlueFactory<->refcount map
  3785. PTR2PLONG::iterator mapIter;
  3786. mapIter = CWbemProviderGlue::s_factorymap.find( pGlue );
  3787. if (mapIter != CWbemProviderGlue::s_factorymap.end())
  3788. {
  3789. pRet = mapIter->second;
  3790. }
  3791. else
  3792. {
  3793. LogErrorMessage2(L"Can't find factory in map: %p", pGlue);
  3794. }
  3795. }
  3796. catch( ... )
  3797. {
  3798. UnlockFactoryMap();
  3799. throw;
  3800. }
  3801. UnlockFactoryMap();
  3802. return pRet;
  3803. }
  3804. /////////////////////////////////////////////////////////////////////
  3805. //
  3806. // Function: CWbemProviderGlue::AddFlushPtr
  3807. //
  3808. // Add the this pointer to a provider to the list of providers
  3809. // that need to be flushed.
  3810. //
  3811. /////////////////////////////////////////////////////////////////////
  3812. void CWbemProviderGlue::AddFlushPtr(LPVOID pVoid)
  3813. {
  3814. CLockWrapper lockwrap(m_csFlushPtrs);
  3815. m_FlushPtrs.insert(pVoid);
  3816. }