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.

986 lines
29 KiB

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