Leaked source code of windows server 2003
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.

4411 lines
139 KiB

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