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

1042 lines
30 KiB

  1. //***************************************************************************
  2. //
  3. // Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
  4. //
  5. // Provider.CPP
  6. //
  7. // Purpose: Implementation of Provider class
  8. //
  9. //***************************************************************************
  10. #include "precomp.h"
  11. #include <assertbreak.h>
  12. #include <objpath.h>
  13. #include <cominit.h>
  14. #include <brodcast.h>
  15. #include <createmutexasprocess.h>
  16. #include <stopwatch.h>
  17. #include <SmartPtr.h>
  18. #include <frqueryex.h>
  19. #include "FWStrings.h"
  20. #include "MultiPlat.h"
  21. // Must instantiate static members
  22. CHString Provider::s_strComputerName;
  23. ////////////////////////////////////////////////////////////////////////
  24. //
  25. // Function: Provider ctor
  26. //
  27. //
  28. //
  29. // Inputs: name of this provider
  30. //
  31. // Outputs:
  32. //
  33. // Return:
  34. //
  35. // Comments: suggest that derived classes implement their provider's ctor thusly:
  36. //
  37. // MyProvider::MyProvider(const CHString& setName) :
  38. // Provider(setName)
  39. //
  40. // that way, a *further* derived class can specify its own name
  41. //
  42. //
  43. ////////////////////////////////////////////////////////////////////////
  44. Provider::Provider( LPCWSTR a_setName, LPCWSTR a_pszNameSpace /*=NULL*/ )
  45. : CThreadBase(),
  46. m_pIMosProvider( NULL ),
  47. m_piClassObject( NULL ),
  48. m_name( a_setName ),
  49. m_strNameSpace( a_pszNameSpace )
  50. {
  51. // Initialize the computer name, then register with the framework.
  52. InitComputerName();
  53. CWbemProviderGlue::FrameworkLogin( a_setName, this, a_pszNameSpace );
  54. }
  55. ////////////////////////////////////////////////////////////////////////
  56. //
  57. // Function: Provider dtor
  58. //
  59. //
  60. //
  61. // Inputs: none.
  62. //
  63. // Outputs:
  64. //
  65. // Return:
  66. //
  67. // Comments: cleans up our pointer to the IMosProvider
  68. //
  69. ////////////////////////////////////////////////////////////////////////
  70. Provider::~Provider( void )
  71. {
  72. // get out of the framework's hair
  73. CWbemProviderGlue::FrameworkLogoff( (LPCWSTR)m_name, (LPCWSTR)m_strNameSpace );
  74. // we can't release the interfaces here because CIMOM has a habit
  75. // of shutting down when it still has interface pointers open.
  76. /********************
  77. // Release the pointer returned to us by GetNamespaceConnection(), which
  78. // will return us an AddRefed pointer.
  79. if ( NULL != m_pIMosProvider )
  80. {
  81. m_pIMosProvider->Release();
  82. }
  83. // The class object is returned to us by IMOSProvider::GetObject, so
  84. // we should try to release it here when we're done with it.
  85. if ( NULL != m_piClassObject )
  86. {
  87. m_piClassObject->Release();
  88. }
  89. ******************************/
  90. }
  91. ////////////////////////////////////////////////////////////////////////
  92. //
  93. // Function: Provider::InitComputerName
  94. //
  95. // Initializes our static computer name variable.
  96. //
  97. // Inputs: None.
  98. //
  99. // Outputs: None.
  100. //
  101. // Return: None.
  102. //
  103. // Comments: Because the idea behind creating providers is that
  104. // a single static instance is instantiated, this function
  105. // will most likely be called as part of DLL loading, we'll
  106. // introduce some thread safety here using a named mutex
  107. // but won't worry too much about it other than that.
  108. //
  109. ////////////////////////////////////////////////////////////////////////
  110. void Provider::InitComputerName( void )
  111. {
  112. // For performance, check if the value is empty. Only if it
  113. // is, should we then bother with going through a thread-safe
  114. // static initialization. Because we are using a named mutex,
  115. // multiple threads will get the same kernel object, and will
  116. // be stop-gapped by the OS as they each acquire the mutex
  117. // in turn.
  118. if ( s_strComputerName.IsEmpty() )
  119. {
  120. CreateMutexAsProcess createMutexAsProcess(WBEMPROVIDERSTATICMUTEX);
  121. // Double check in case there was a conflict and somebody else
  122. // got here first.
  123. if ( s_strComputerName.IsEmpty() )
  124. {
  125. DWORD dwBuffSize = MAX_COMPUTERNAME_LENGTH + 1;
  126. // Make sure the string buffer will be big enough to handle the
  127. // value.
  128. LPWSTR pszBuffer = s_strComputerName.GetBuffer( dwBuffSize );
  129. if ( NULL != pszBuffer )
  130. {
  131. // Now grab the computer name and release the buffer, forcing
  132. // it to reallocate itself to the new length.
  133. if (!FRGetComputerName( pszBuffer, &dwBuffSize )) {
  134. wcscpy(pszBuffer, L"DEFAULT");
  135. }
  136. s_strComputerName.ReleaseBuffer();
  137. } // IF NULL != pszBuffer
  138. } // IF strComputerName.IsEmpty()
  139. } // IF strComputerName.IsEmpty()
  140. }
  141. ////////////////////////////////////////////////////////////////////////
  142. //
  143. // Function: Flush
  144. //
  145. // flushes out all unnecessary memory usage
  146. // inlcuding the (unimplemented) cache
  147. // and the class object we clone from
  148. //
  149. // Inputs: nope
  150. //
  151. // Outputs:
  152. //
  153. // Return: the eternal void
  154. //
  155. // Comments:
  156. //
  157. ////////////////////////////////////////////////////////////////////////
  158. void Provider::Flush()
  159. {
  160. // TODO: implement cache flush
  161. BeginWrite();
  162. try
  163. {
  164. if (m_piClassObject)
  165. {
  166. m_piClassObject->Release();
  167. m_piClassObject = NULL;
  168. }
  169. if ( NULL != m_pIMosProvider )
  170. {
  171. m_pIMosProvider->Release();
  172. m_pIMosProvider = NULL;
  173. }
  174. }
  175. catch ( ... )
  176. {
  177. EndWrite();
  178. throw;
  179. }
  180. EndWrite();
  181. }
  182. ////////////////////////////////////////////////////////////////////////
  183. //
  184. // Function: ValidateIMOSPointer
  185. //
  186. // Verifies in a threadsafe manner, that our IWBEMServices pointer
  187. // is okay.
  188. //
  189. // Inputs: None.
  190. //
  191. // Outputs:
  192. //
  193. // Return: TRUE/FALSE success/failure
  194. //
  195. // Comments: Requires that our NameSpace be valid.
  196. //
  197. ////////////////////////////////////////////////////////////////////////
  198. BOOL Provider::ValidateIMOSPointer( )
  199. {
  200. // if we don't have a Namespace connection, get one. Be aware that for
  201. // speed's sake we are testing the value outside of a critical section, but
  202. // because two threads may enter this block of code simultaneously, this
  203. // block is testing one more time inside the critical sections.
  204. // if ( NULL == m_pIMosProvider )
  205. // {
  206. // BeginWrite();
  207. //
  208. // try
  209. // {
  210. //
  211. // // See above (it's a redundant test), but keeps us from leaking and
  212. // // overwriting the value twice.
  213. //
  214. // if ( NULL == m_pIMosProvider )
  215. // {
  216. // m_pIMosProvider = CWbemProviderGlue::GetNamespaceConnection( m_strNameSpace, pwszIID );
  217. // }
  218. // }
  219. // catch ( ... )
  220. // {
  221. // EndWrite();
  222. // throw;
  223. // }
  224. //
  225. // EndWrite();
  226. // }
  227. //
  228. // if (m_pIMosProvider == NULL)
  229. // {
  230. // throw CFramework_Exception(L"ValidateIMOSPointer failed");
  231. // }
  232. //
  233. // return ( NULL != m_pIMosProvider );
  234. return TRUE;
  235. }
  236. ////////////////////////////////////////////////////////////////////////
  237. //
  238. // Function: CreateNewInstance
  239. //
  240. //
  241. //
  242. // Inputs: MethodContext* - context that this instance belongs to
  243. //
  244. // Outputs:
  245. //
  246. // Return: CInstance*
  247. //
  248. // Comments: caller is responsible for memory
  249. //
  250. ////////////////////////////////////////////////////////////////////////
  251. CInstance* Provider::CreateNewInstance( MethodContext* pMethodContext )
  252. {
  253. HRESULT hr = WBEM_S_NO_ERROR;
  254. CInstance* pNewInstance = NULL;
  255. IWbemClassObjectPtr pClassObject (GetClassObjectInterface(pMethodContext), false);
  256. IWbemClassObjectPtr piClone;
  257. hr = pClassObject->SpawnInstance(0, &piClone);
  258. if (SUCCEEDED(hr))
  259. {
  260. // The Instance is responsible for its own AddRef/Releasing
  261. pNewInstance = new CInstance(piClone, pMethodContext);
  262. if (pNewInstance == NULL)
  263. {
  264. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  265. }
  266. }
  267. else
  268. {
  269. throw CFramework_Exception(L"SpawnInstance failed", hr);
  270. }
  271. return pNewInstance;
  272. }
  273. ////////////////////////////////////////////////////////////////////////
  274. //
  275. // Function: Commit
  276. //
  277. // sends instance to CIMOM
  278. //
  279. // Inputs: CInstance* pInstance - the instance to pass off to cimom,
  280. // bool bCache - should we cache this puppy? (unimplemented)
  281. //
  282. // Outputs:
  283. //
  284. // Return:
  285. //
  286. // Comments: do not reference pointer once committed, it may not exist any more!
  287. //
  288. ////////////////////////////////////////////////////////////////////////
  289. HRESULT Provider::Commit(CInstance* pInstance, bool bCache /* = false*/)
  290. {
  291. HRESULT hRes = WBEM_S_NO_ERROR;
  292. // allow derived classes to fill out extra info.
  293. // GetExtendedProperties(pInstance);
  294. hRes = pInstance->Commit();
  295. // TODO: Implement cache
  296. // if !bCache...
  297. // We're done with pInstance, so...
  298. pInstance->Release();
  299. return hRes;
  300. }
  301. ////////////////////////////////////////////////////////////////////////
  302. //
  303. // Function: ExecuteQuery
  304. //
  305. //
  306. //
  307. // Inputs: IWbemContext __RPC_FAR * pCtx,
  308. //
  309. // Outputs:
  310. //
  311. // Return: HRESULT
  312. //
  313. // Comments: Calls a provider's ExecQuery function, or returns
  314. //
  315. ////////////////////////////////////////////////////////////////////////
  316. HRESULT Provider::ExecuteQuery( MethodContext* pContext, CFrameworkQuery& pQuery, long lFlags /*= 0L*/ )
  317. {
  318. HRESULT hr = ValidateQueryFlags(lFlags);
  319. // Make sure we've got Managed Object Services avaliable, as we will need
  320. // it to get WBEMClassObjects for constructing Instances.
  321. if ( SUCCEEDED(hr) && ValidateIMOSPointer( ) )
  322. {
  323. // Check to see if this is an extended query
  324. CFrameworkQueryEx *pQuery2 = static_cast <CFrameworkQueryEx*>(&pQuery);
  325. if (pQuery2->IsExtended())
  326. {
  327. // It is an extended query. Does the provider support them?
  328. if (FAILED(ValidateQueryFlags(WBEM_FLAG_FORWARD_ONLY)))
  329. {
  330. // We have an extended query, but the provider doesn't support it
  331. hr = WBEM_E_INVALID_QUERY;
  332. }
  333. }
  334. if (SUCCEEDED(hr))
  335. {
  336. // Tell cimom he's got work to do on the instances when we send
  337. // them back.
  338. pContext->QueryPostProcess();
  339. // If the client hasn't overridden the class, we get back
  340. // WBEM_E_PROVIDER_NOT_CAPABLE. In that case, call the enumerate, and let
  341. // CIMOM do the work
  342. PROVIDER_INSTRUMENTATION_START(pContext, StopWatch::ProviderTimer);
  343. hr = ExecQuery(pContext, pQuery, lFlags);
  344. PROVIDER_INSTRUMENTATION_START(pContext, StopWatch::FrameworkTimer);
  345. if (hr == WBEM_E_PROVIDER_NOT_CAPABLE)
  346. {
  347. // Get the instances
  348. PROVIDER_INSTRUMENTATION_START(pContext, StopWatch::ProviderTimer);
  349. hr = CreateInstanceEnum(pContext, lFlags);
  350. PROVIDER_INSTRUMENTATION_START(pContext, StopWatch::FrameworkTimer);
  351. }
  352. }
  353. else
  354. {
  355. hr = WBEM_E_INVALID_QUERY;
  356. }
  357. }
  358. return hr;
  359. }
  360. ////////////////////////////////////////////////////////////////////////
  361. //
  362. // Function: CreateInstanceEnum
  363. //
  364. //
  365. //
  366. // Inputs: IWbemContext __RPC_FAR * pCtx,
  367. // IWbemObjectSink __RPC_FAR * pResponseHandler
  368. // Outputs:
  369. //
  370. // Return:
  371. //
  372. // Comments: enumerate all instances of this class
  373. //
  374. ////////////////////////////////////////////////////////////////////////
  375. HRESULT Provider::CreateInstanceEnum( MethodContext* pContext, long lFlags /*= 0L*/ )
  376. {
  377. HRESULT sc = ValidateEnumerationFlags(lFlags);
  378. // Make sure we've got Managed Object Services avaliable, as we will need
  379. // it to get WBEMClassObjects for constructing Instances.
  380. if ( SUCCEEDED(sc) && ValidateIMOSPointer( ) )
  381. {
  382. PROVIDER_INSTRUMENTATION_START(pContext, StopWatch::ProviderTimer);
  383. sc = EnumerateInstances( pContext, lFlags );
  384. PROVIDER_INSTRUMENTATION_START(pContext, StopWatch::FrameworkTimer);
  385. }
  386. return sc;
  387. }
  388. ////////////////////////////////////////////////////////////////////////
  389. //
  390. // Function: PutInstance
  391. //
  392. // CIMOM wants us to put this instance.
  393. //
  394. // Inputs:
  395. //
  396. // Outputs:
  397. //
  398. // Return:
  399. //
  400. // Comments:
  401. //
  402. ////////////////////////////////////////////////////////////////////////
  403. HRESULT Provider::PutInstance(const CInstance& newInstance, long lFlags /*= 0L*/)
  404. {
  405. return WBEM_E_PROVIDER_NOT_CAPABLE;
  406. }
  407. ////////////////////////////////////////////////////////////////////////
  408. //
  409. // Function: PutInstance
  410. //
  411. // CIMOM wants us to put this instance.
  412. //
  413. // Inputs:
  414. //
  415. // Outputs:
  416. //
  417. // Return:
  418. //
  419. // Comments:
  420. //
  421. ////////////////////////////////////////////////////////////////////////
  422. HRESULT Provider::PutInstance( IWbemClassObject __RPC_FAR *pInst,
  423. long lFlags,
  424. MethodContext* pContext )
  425. {
  426. HRESULT scode = ValidatePutInstanceFlags(lFlags);
  427. // No need to AddRef()/Release() pInst here, since we're just
  428. // passing it into the CInstance object, which should take
  429. // care of that for us internally.
  430. if (SUCCEEDED(scode))
  431. {
  432. CInstancePtr pInstance (new CInstance( pInst, pContext ), false);
  433. if ( NULL != pInstance )
  434. {
  435. scode = PutInstance(*pInstance, lFlags);
  436. }
  437. else
  438. {
  439. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  440. }
  441. }
  442. return scode;
  443. }
  444. ////////////////////////////////////////////////////////////////////////
  445. //
  446. // Function: DeleteInstance
  447. //
  448. // CIMOM wants us to delete this instance.
  449. //
  450. // Inputs:
  451. //
  452. // Outputs:
  453. //
  454. // Return:
  455. //
  456. // Comments:
  457. //
  458. ////////////////////////////////////////////////////////////////////////
  459. HRESULT Provider::DeleteInstance(const CInstance& newInstance, long lFlags /*= 0L*/)
  460. {
  461. return WBEM_E_PROVIDER_NOT_CAPABLE;
  462. }
  463. ////////////////////////////////////////////////////////////////////////
  464. //
  465. // Function: DeleteInstance
  466. //
  467. // CIMOM wants us to put this instance.
  468. //
  469. // Inputs:
  470. //
  471. // Outputs:
  472. //
  473. // Return:
  474. //
  475. // Comments:
  476. //
  477. ////////////////////////////////////////////////////////////////////////
  478. HRESULT Provider::DeleteInstance( ParsedObjectPath* pParsedObjectPath,
  479. long lFlags,
  480. MethodContext* pContext )
  481. {
  482. HRESULT sc = ValidateDeletionFlags(lFlags);
  483. // Make sure we've got Managed Object Services avaliable, as we will
  484. // need it in order to create a brand new instance.
  485. if ( SUCCEEDED(sc) && ValidateIMOSPointer( ) )
  486. {
  487. CInstancePtr pInstance (CreateNewInstance( pContext ), false);
  488. // Load up the instance keys
  489. if ( SetKeyFromParsedObjectPath( pInstance, pParsedObjectPath ) )
  490. {
  491. sc = DeleteInstance(*pInstance, lFlags);
  492. }
  493. else
  494. {
  495. sc = WBEM_E_INVALID_OBJECT_PATH;
  496. }
  497. }
  498. return sc;
  499. }
  500. ////////////////////////////////////////////////////////////////////////
  501. //
  502. // Function: ExecMethod
  503. //
  504. // CIMOM wants us to execute this method on this instance
  505. //
  506. // Inputs:
  507. //
  508. // Outputs:
  509. //
  510. // Return:
  511. //
  512. // Comments:
  513. //
  514. ////////////////////////////////////////////////////////////////////////
  515. HRESULT Provider::ExecMethod(const CInstance& pInstance,
  516. BSTR bstrMethodName,
  517. CInstance *pInParams,
  518. CInstance *pOutParams,
  519. long lFlags /*= 0L*/)
  520. {
  521. return WBEM_E_PROVIDER_NOT_CAPABLE;
  522. }
  523. ////////////////////////////////////////////////////////////////////////
  524. //
  525. // Function: ExecMethod
  526. //
  527. // CIMOM wants us to Execute this method on this instance
  528. //
  529. // Inputs:
  530. //
  531. // Outputs:
  532. //
  533. // Return:
  534. //
  535. // Comments:
  536. //
  537. ////////////////////////////////////////////////////////////////////////
  538. HRESULT Provider::ExecMethod( ParsedObjectPath *pParsedObjectPath,
  539. BSTR bstrMethodName,
  540. long lFlags,
  541. CInstance *pInParams,
  542. CInstance *pOutParams,
  543. MethodContext *pContext )
  544. {
  545. HRESULT sc = ValidateMethodFlags(lFlags);
  546. // Make sure we've got Managed Object Services avaliable, as we will
  547. // need it in order to create a brand new instance.
  548. if ( SUCCEEDED(sc) && ValidateIMOSPointer( ) )
  549. {
  550. CInstancePtr pInstance(CreateNewInstance( pContext ), false);
  551. if ( SetKeyFromParsedObjectPath( pInstance, pParsedObjectPath ) )
  552. {
  553. PROVIDER_INSTRUMENTATION_START(pContext, StopWatch::ProviderTimer);
  554. sc = ExecMethod(*pInstance, bstrMethodName, pInParams, pOutParams, lFlags);
  555. PROVIDER_INSTRUMENTATION_START(pContext, StopWatch::FrameworkTimer);
  556. }
  557. else
  558. {
  559. sc = WBEM_E_INVALID_OBJECT_PATH;
  560. }
  561. }
  562. return sc;
  563. }
  564. ////////////////////////////////////////////////////////////////////////
  565. //
  566. // Function: GetObject
  567. //
  568. // called by the framework in response to a GetObject from CIMOM
  569. //
  570. // Inputs: ParsedObjectPath* pParsedObjectPath - All the news
  571. // thats fit to print.
  572. // IWbemContext __RPC_FAR* pCtx
  573. // IWbemObjectSink __RPC_FAR*pResponseHandler
  574. //
  575. //
  576. // Outputs:
  577. //
  578. // Return:
  579. //
  580. // Comments:
  581. //
  582. ////////////////////////////////////////////////////////////////////////
  583. HRESULT Provider::GetObject( ParsedObjectPath *pParsedObjectPath,
  584. MethodContext *pContext,
  585. long lFlags /*= 0L*/ )
  586. {
  587. HRESULT hr = ValidateGetObjFlags(lFlags);
  588. // Make sure we've got Managed Object Services avaliable, as we will
  589. // need it in order to create a brand new instance.
  590. if ( SUCCEEDED(hr) && ValidateIMOSPointer( ) )
  591. {
  592. CInstancePtr pInstance (CreateNewInstance( pContext ), false);
  593. // Load up the instance keys
  594. if ( SetKeyFromParsedObjectPath( pInstance, pParsedObjectPath ) )
  595. {
  596. // Look for per-property gets
  597. IWbemContextPtr pWbemContext (pContext->GetIWBEMContext(), false);
  598. CFrameworkQueryEx CQuery;
  599. hr = CQuery.Init(pParsedObjectPath, pWbemContext, GetProviderName(), m_strNameSpace);
  600. // Note that 'SUCCEEDED' DOESN'T mean that we have per-property gets. It
  601. // just means that the query object was successfully initialized.
  602. if (SUCCEEDED(hr))
  603. {
  604. // Fill in key properties on query object
  605. IWbemClassObjectPtr pWbemClassObject(pInstance->GetClassObjectInterface(), false);
  606. CQuery.Init2(pWbemClassObject);
  607. PROVIDER_INSTRUMENTATION_START(pContext, StopWatch::ProviderTimer);
  608. hr = GetObject(pInstance, lFlags, CQuery);
  609. PROVIDER_INSTRUMENTATION_START(pContext, StopWatch::FrameworkTimer);
  610. }
  611. }
  612. else
  613. {
  614. hr = WBEM_E_INVALID_OBJECT_PATH;
  615. }
  616. if (SUCCEEDED(hr))
  617. {
  618. // Account for the possibility that we have a SUCCESS code back from GetObject.
  619. HRESULT hRes = pInstance->Commit();
  620. hr = __max((ULONG)hRes, (ULONG)hr);
  621. }
  622. }
  623. return hr;
  624. }
  625. ////////////////////////////////////////////////////////////////////////
  626. //
  627. // Function: Provider::GetInstancePath
  628. //
  629. // Attempts to build an instance path for the supplied CInstance pointer.
  630. //
  631. // Inputs: const CInstance* pInstance - Instance to build path for.
  632. //
  633. // Outputs: CHString& strPath - Path from instance.
  634. //
  635. // Return: BOOL Success/Failure.
  636. //
  637. // Comments: This function was created to help support the internal
  638. // short circuit we performed for obtaining local WBEM
  639. // Provider objects. In this instance, we will use our
  640. // computer system name, namespace and instance relative
  641. // path to munge together a full WBEM Object Path. This
  642. // is because only CIMOM objects will have this value set
  643. // and when we perform our short circuit, we cut CIMOM
  644. // out of the loop, so our instances don't have full
  645. // object paths. This mostly helps out our association
  646. // logic, although a weakness of this solution is that
  647. // if the path that gets stored by CIMOM changes, we
  648. // will then need to change this function.
  649. //
  650. ////////////////////////////////////////////////////////////////////////
  651. bool Provider::GetLocalInstancePath( const CInstance *pInstance,
  652. CHString& strPath )
  653. {
  654. bool fReturn = false;
  655. CHString strRelativePath;
  656. if (pInstance && pInstance->GetCHString( L"__RELPATH", strRelativePath ) )
  657. {
  658. // We may want to use the OBJPath classes to piece this
  659. // together for us at a later time.
  660. strPath = MakeLocalPath(strRelativePath);
  661. fReturn = true;
  662. }
  663. return fReturn;
  664. }
  665. ////////////////////////////////////////////////////////////////////////
  666. //
  667. // Function: Provider::MakeLocalPath
  668. //
  669. // Builds a full instance path from a relative path
  670. //
  671. // Inputs: const CHString &strRelPath - Relative path
  672. //
  673. // Outputs:
  674. //
  675. // Return: CHString& strPath - Path
  676. //
  677. // Comments: Consider using GetLocalInstance path before using
  678. // this function.
  679. //
  680. ////////////////////////////////////////////////////////////////////////
  681. CHString Provider::MakeLocalPath( const CHString &strRelPath )
  682. {
  683. ASSERT_BREAK( (strRelPath.Find(L':') == -1) || ((strRelPath.Find(L'=') != -1) && (strRelPath.Find(L':') >= strRelPath.Find(L'=')) ));
  684. CHString sBase;
  685. sBase.Format(L"\\\\%s\\%s:%s",
  686. (LPCWSTR)s_strComputerName,
  687. m_strNameSpace.IsEmpty() ? DEFAULT_NAMESPACE: (LPCWSTR) m_strNameSpace,
  688. (LPCWSTR)strRelPath);
  689. return sBase;
  690. }
  691. ////////////////////////////////////////////////////////////////////////
  692. //
  693. // Function: SetKeyFromParsedObjectPath
  694. //
  695. // called by the DeleteInstance and GetObject in order to load a
  696. // CInstance* with the key values in an object path.
  697. //
  698. // Inputs: CInstance* pInstance - Instance to store
  699. // key values in.
  700. // ParsedObjectPath* pParsedObjectPath - All the news
  701. // thats fit to print.
  702. //
  703. //
  704. // Outputs:
  705. //
  706. // Return: BOOL Success/Failure
  707. //
  708. // Comments:
  709. //
  710. ////////////////////////////////////////////////////////////////////////
  711. BOOL Provider::SetKeyFromParsedObjectPath( CInstance *pInstance,
  712. ParsedObjectPath *pParsedPath )
  713. {
  714. BOOL fReturn = TRUE;
  715. SAFEARRAY *pNames = NULL;
  716. long lLBound, lUBound;
  717. // populate instance - This exact same routine is in wbemglue.cpp. Changes here should be
  718. // reflected there (or someone should move these two somewhere else. instance.cpp?).
  719. for (DWORD i = 0; fReturn && i < (pParsedPath->m_dwNumKeys); i++)
  720. {
  721. if (pParsedPath->m_paKeys[i])
  722. {
  723. // If a name was specified in the form class.keyname=value
  724. if (pParsedPath->m_paKeys[i]->m_pName != NULL)
  725. {
  726. fReturn = pInstance->SetVariant(pParsedPath->m_paKeys[i]->m_pName, pParsedPath->m_paKeys[i]->m_vValue);
  727. }
  728. else
  729. {
  730. // There is a special case that you can say class=value
  731. fReturn = FALSE;
  732. // only one key allowed in the format. Check the names on the path
  733. if (pParsedPath->m_dwNumKeys == 1)
  734. {
  735. // Get the names from the object
  736. if (m_piClassObject->GetNames(NULL, WBEM_FLAG_KEYS_ONLY, NULL, &pNames) == WBEM_S_NO_ERROR)
  737. {
  738. BSTR t_bstrName = NULL ;
  739. try
  740. {
  741. SafeArrayGetLBound(pNames, 1, &lLBound);
  742. SafeArrayGetUBound(pNames, 1, &lUBound);
  743. // Only one key?
  744. if ((lUBound - lLBound) == 0)
  745. {
  746. // Get the name of the key field and set it
  747. SafeArrayGetElement(pNames, &lUBound, &t_bstrName );
  748. fReturn = pInstance->SetVariant( t_bstrName, pParsedPath->m_paKeys[i]->m_vValue);
  749. }
  750. }
  751. catch ( ... )
  752. {
  753. if( NULL != t_bstrName )
  754. {
  755. SysFreeString( t_bstrName ) ;
  756. }
  757. SafeArrayDestroy(pNames);
  758. throw;
  759. }
  760. SafeArrayDestroy(pNames);
  761. }
  762. }
  763. ASSERT_BREAK(fReturn); // somebody lied about the number of keys or the datatype was wrong
  764. }
  765. }
  766. else
  767. {
  768. ASSERT_BREAK(0); // somebody lied about the number of keys!
  769. fReturn = FALSE;
  770. }
  771. }
  772. return fReturn;
  773. }
  774. // sets the CreationClassName to the name of this provider
  775. bool Provider::SetCreationClassName(CInstance* pInstance)
  776. {
  777. if (pInstance)
  778. {
  779. return pInstance->SetCHString(IDS_CreationClassName, m_name);
  780. }
  781. else
  782. {
  783. return false;
  784. }
  785. }
  786. // flag validation - returns WBEM_E_UNSUPPORTED parameter if
  787. // lFlags contains any flags not found in lAcceptableFlags
  788. HRESULT Provider::ValidateFlags(long lFlags, FlagDefs lAcceptableFlags)
  789. {
  790. HRESULT hr = WBEM_S_NO_ERROR;
  791. // invert the acceptable flags, which then are the UNacceptable flags
  792. if (lFlags & ~((long)lAcceptableFlags))
  793. hr = WBEM_E_UNSUPPORTED_PARAMETER;
  794. else
  795. hr = WBEM_S_NO_ERROR;
  796. return hr;
  797. }
  798. // base level validation routines
  799. // you can override these in order to support a flag
  800. // that is unknown to the base class
  801. HRESULT Provider::ValidateEnumerationFlags(long lFlags)
  802. {
  803. return ValidateFlags(lFlags, EnumerationFlags);
  804. }
  805. HRESULT Provider::ValidateGetObjFlags(long lFlags)
  806. {
  807. return ValidateFlags(lFlags, GetObjFlags);
  808. }
  809. HRESULT Provider::ValidateMethodFlags(long lFlags)
  810. {
  811. return ValidateFlags(lFlags, MethodFlags);
  812. }
  813. HRESULT Provider::ValidateQueryFlags(long lFlags)
  814. {
  815. return ValidateFlags(lFlags, QueryFlags);
  816. }
  817. HRESULT Provider::ValidateDeletionFlags(long lFlags)
  818. {
  819. return ValidateFlags(lFlags, DeletionFlags);
  820. }
  821. HRESULT Provider::ValidatePutInstanceFlags(long lFlags)
  822. {
  823. return ValidateFlags(lFlags, PutInstanceFlags);
  824. }
  825. IWbemClassObject* Provider::GetClassObjectInterface(MethodContext *pMethodContext)
  826. {
  827. IWbemClassObject *pObject = NULL;
  828. if (ValidateIMOSPointer())
  829. {
  830. BOOL bWriting = TRUE;
  831. BeginWrite();
  832. try
  833. {
  834. if ( NULL == m_piClassObject )
  835. {
  836. bWriting = FALSE;
  837. //calling back into winmgmt - no critsec!
  838. EndWrite();
  839. IWbemContextPtr pWbemContext;
  840. if ( NULL != pMethodContext )
  841. {
  842. pWbemContext.Attach(pMethodContext->GetIWBEMContext());
  843. }
  844. IWbemServicesPtr pServices(CWbemProviderGlue::GetNamespaceConnection( m_strNameSpace, pMethodContext ), false);
  845. HRESULT hr = pServices->GetObject( bstr_t( m_name ), 0L, pWbemContext, &pObject, NULL);
  846. BeginWrite();
  847. bWriting = TRUE;
  848. if (SUCCEEDED(hr))
  849. {
  850. if (m_piClassObject == NULL)
  851. {
  852. m_piClassObject = pObject;
  853. pObject->AddRef();
  854. }
  855. }
  856. else
  857. {
  858. // belt & suspenders check. Won't hurt.
  859. m_piClassObject = NULL;
  860. throw CFramework_Exception(L"SpawnInstance failed", hr);
  861. }
  862. }
  863. else
  864. {
  865. pObject = m_piClassObject;
  866. pObject->AddRef();
  867. }
  868. }
  869. catch ( ... )
  870. {
  871. if (bWriting)
  872. {
  873. EndWrite();
  874. }
  875. if (pObject)
  876. {
  877. pObject->Release();
  878. pObject = NULL;
  879. }
  880. throw;
  881. }
  882. EndWrite();
  883. }
  884. return pObject;
  885. }
  886. // If a provider wants to process queries, they should override this
  887. HRESULT Provider::ExecQuery(MethodContext *pMethodContext, CFrameworkQuery& pQuery, long lFlags /*= 0L*/)
  888. {
  889. return WBEM_E_PROVIDER_NOT_CAPABLE;
  890. }
  891. // find and create all instances of your class
  892. HRESULT Provider::EnumerateInstances(MethodContext* pMethodContext, long lFlags /*= 0L*/)
  893. {
  894. return WBEM_E_PROVIDER_NOT_CAPABLE;
  895. }
  896. // you will be given an object with the key properties filled in.
  897. // you need to fill in all of the rest of the properties
  898. HRESULT Provider::GetObject(CInstance* pInstance, long lFlags /*= 0L*/)
  899. {
  900. return WBEM_E_PROVIDER_NOT_CAPABLE;
  901. }
  902. // You will be given an object with the key properties filled in.
  903. // You can either fill in all the properties, or check the Query object
  904. // to see what properties are required.
  905. HRESULT Provider::GetObject(CInstance *pInstance, long lFlags, CFrameworkQuery &Query)
  906. {
  907. // If we are here, the provider didn't override this method. Fall back to the older
  908. // call.
  909. return GetObject(pInstance, lFlags);
  910. }