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.

621 lines
21 KiB

  1. ////////////////////////////////////////////////////////////////////////
  2. //
  3. // Provider.cpp
  4. //
  5. // Module: WMI high performance provider
  6. //
  7. //
  8. // History:
  9. // a-dcrews 12-Jan-97 Created
  10. //
  11. //
  12. // Copyright (c) 1997-2001 Microsoft Corporation
  13. //
  14. ////////////////////////////////////////////////////////////////////////
  15. #include "precomp.h"
  16. #include <process.h>
  17. #include <autoptr.h>
  18. #include "Provider.h"
  19. #include "CookerUtils.h"
  20. #include <comdef.h>
  21. //////////////////////////////////////////////////////////////
  22. //
  23. //
  24. // Global, external and static variables
  25. //
  26. //
  27. //////////////////////////////////////////////////////////////
  28. // The COM object counter (declared in server.cpp)
  29. // ===============================================
  30. extern long g_lObjects;
  31. //////////////////////////////////////////////////////////////
  32. //
  33. //
  34. // CHiPerfProvider
  35. //
  36. //
  37. //////////////////////////////////////////////////////////////
  38. CHiPerfProvider::CHiPerfProvider() : m_lRef(0)
  39. {
  40. // Increment the global COM object counter
  41. InterlockedIncrement(&g_lObjects);
  42. }
  43. CHiPerfProvider::~CHiPerfProvider()
  44. {
  45. // Decrement the global COM object counter
  46. InterlockedDecrement(&g_lObjects);
  47. }
  48. //////////////////////////////////////////////////////////////
  49. //
  50. // COM methods
  51. //
  52. //////////////////////////////////////////////////////////////
  53. STDMETHODIMP CHiPerfProvider::QueryInterface(REFIID riid, void** ppv)
  54. //////////////////////////////////////////////////////////////
  55. //
  56. // Standard QueryInterface
  57. //
  58. // Parameters:
  59. // riid - the ID of the requested interface
  60. // ppv - a pointer to the interface pointer
  61. //
  62. //////////////////////////////////////////////////////////////
  63. //ok
  64. {
  65. if (NULL == ppv) return E_POINTER;
  66. if(riid == IID_IUnknown)
  67. *ppv = (LPVOID)(IUnknown*)(IWbemProviderInit*)this;
  68. else if(riid == IID_IWbemProviderInit)
  69. *ppv = (LPVOID)(IWbemProviderInit*)this;
  70. else if (riid == IID_IWbemHiPerfProvider)
  71. *ppv = (LPVOID)(IWbemHiPerfProvider*)this;
  72. else
  73. {
  74. *ppv = NULL;
  75. return E_NOINTERFACE;
  76. }
  77. ((IUnknown*)*ppv)->AddRef();
  78. return WBEM_NO_ERROR;
  79. }
  80. STDMETHODIMP_(ULONG) CHiPerfProvider::AddRef()
  81. {
  82. return InterlockedIncrement(&m_lRef);
  83. }
  84. STDMETHODIMP_(ULONG) CHiPerfProvider::Release()
  85. {
  86. long lRef = InterlockedDecrement(&m_lRef);
  87. if(lRef == 0) delete this;
  88. return lRef;
  89. }
  90. STDMETHODIMP CHiPerfProvider::Initialize(
  91. /* [unique][in] */ LPWSTR wszUser,
  92. /* [in] */ long lFlags,
  93. /* [in] */ LPWSTR wszNamespace,
  94. /* [unique][in] */ LPWSTR wszLocale,
  95. /* [in] */ IWbemServices __RPC_FAR *pNamespace,
  96. /* [in] */ IWbemContext __RPC_FAR *pCtx,
  97. /* [in] */ IWbemProviderInitSink __RPC_FAR *pInitSink)
  98. //////////////////////////////////////////////////////////////////////
  99. //
  100. // Called once during startup for any one-time initialization. The
  101. // final call to Release() is for any cleanup.
  102. //
  103. // The parameters indicate to the provider which namespace it is being
  104. // invoked for and which User. It also supplies a back pointer to
  105. // WINMGMT so that class definitions can be retrieved.
  106. //
  107. // Initialize will create a single template object that can be used
  108. // by the provider to spawn instances for QueryInstances. It will
  109. // also initialize our mock data source and set the global ID access
  110. // handle.
  111. //
  112. // Parameters:
  113. // wszUser - The current user.
  114. // lFlags - Reserved.
  115. // wszNamespace - The namespace for which we are being activated.
  116. // wszLocale - The locale under which we are to be running.
  117. // pNamespace - An active pointer back into the current namespace
  118. // from which we can retrieve schema objects.
  119. // pCtx - The user's context object. We simply reuse this
  120. // during any reentrant operations into WINMGMT.
  121. // pInitSink - The sink to which we indicate our readiness.
  122. //
  123. //////////////////////////////////////////////////////////////////////
  124. //ok
  125. {
  126. if (wszNamespace == 0 || pNamespace == 0 || pInitSink == 0)
  127. return WBEM_E_INVALID_PARAMETER;
  128. // We now have all the instances ready to go and the name handle
  129. // stored. Tell WINMGMT that we're ready to start 'providing'
  130. pInitSink->SetStatus(WBEM_S_INITIALIZED, 0);
  131. return WBEM_NO_ERROR;
  132. }
  133. STDMETHODIMP CHiPerfProvider::CreateRefresher(
  134. /* [in] */ IWbemServices __RPC_FAR *pNamespace,
  135. /* [in] */ long lFlags,
  136. /* [out] */ IWbemRefresher __RPC_FAR *__RPC_FAR *ppRefresher )
  137. //////////////////////////////////////////////////////////////////////
  138. //
  139. // Called whenever a new refresher is needed by the client.
  140. //
  141. // Parameters:
  142. // pNamespace - A pointer to the relevant namespace. Not used.
  143. // lFlags - Reserved.
  144. // ppRefresher - Receives the requested refresher.
  145. //
  146. //////////////////////////////////////////////////////////////////////
  147. //ok
  148. {
  149. HRESULT hResult = WBEM_NO_ERROR;
  150. if ( pNamespace == 0 || ppRefresher == 0 )
  151. hResult = WBEM_E_INVALID_PARAMETER;
  152. if ( SUCCEEDED( hResult ) )
  153. {
  154. // Construct and initialize a new empty refresher
  155. // ==============================================
  156. CRefresher* pNewRefresher = new CRefresher;
  157. if ( NULL == pNewRefresher )
  158. {
  159. hResult = WBEM_E_OUT_OF_MEMORY;
  160. }
  161. else if ( !pNewRefresher->IsOK() )
  162. {
  163. hResult = WBEM_E_CRITICAL_ERROR;
  164. }
  165. if ( SUCCEEDED( hResult ) )
  166. {
  167. // Follow COM rules and AddRef() the thing before sending it back
  168. // ==============================================================
  169. pNewRefresher->AddRef();
  170. *ppRefresher = pNewRefresher;
  171. }
  172. else
  173. {
  174. delete pNewRefresher;
  175. }
  176. }
  177. return hResult;
  178. }
  179. STDMETHODIMP CHiPerfProvider::CreateRefreshableObject(
  180. /* [in] */ IWbemServices __RPC_FAR *pNamespace,
  181. /* [in] */ IWbemObjectAccess __RPC_FAR *pTemplate,
  182. /* [in] */ IWbemRefresher __RPC_FAR *pRefresher,
  183. /* [in] */ long lFlags,
  184. /* [in] */ IWbemContext __RPC_FAR *pContext,
  185. /* [out] */ IWbemObjectAccess __RPC_FAR *__RPC_FAR *ppRefreshable,
  186. /* [out] */ long __RPC_FAR *plId )
  187. //////////////////////////////////////////////////////////////////////
  188. //
  189. // Called whenever a user wants to include an object in a refresher.
  190. //
  191. // Note that the object returned in ppRefreshable is a clone of the
  192. // actual instance maintained by the provider. If refreshers shared
  193. // a copy of the same instance, then a refresh call on one of the
  194. // refreshers would impact the state of both refreshers. This would
  195. // break the refresher rules. Instances in a refresher are only
  196. // allowed to be updated when 'Refresh' is called.
  197. //
  198. // Parameters:
  199. // pNamespace - A pointer to the relevant namespace in WINMGMT.
  200. // pTemplate - A pointer to a copy of the object which is to be
  201. // added. This object itself cannot be used, as
  202. // it not owned locally.
  203. // pRefresher - The refresher to which to add the object.
  204. // lFlags - Not used.
  205. // pContext - Not used here.
  206. // ppRefreshable - A pointer to the internal object which was added
  207. // to the refresher.
  208. // plId - The Object Id (for identification during removal).
  209. //
  210. //////////////////////////////////////////////////////////////////////
  211. //ok
  212. {
  213. HRESULT hResult = WBEM_NO_ERROR;
  214. if ( pNamespace == 0 || pTemplate == 0 || pRefresher == 0 )
  215. hResult = WBEM_E_INVALID_PARAMETER;
  216. // Verify hi-perf object
  217. // =====================
  218. if ( !IsHiPerfObj( pTemplate ) )
  219. hResult = WBEM_E_INVALID_CLASS;
  220. _variant_t VarClass;
  221. hResult = pTemplate->Get(L"__CLASS",0,&VarClass,NULL,NULL);
  222. if ( SUCCEEDED( hResult ) )
  223. {
  224. if (VT_BSTR == V_VT(&VarClass))
  225. {
  226. if ( !IsHiPerf( pNamespace, V_BSTR(&VarClass) ) )
  227. {
  228. hResult = WBEM_E_INVALID_CLASS;
  229. }
  230. }
  231. else
  232. {
  233. hResult = WBEM_E_INVALID_CLASS;
  234. }
  235. }
  236. if ( SUCCEEDED( hResult ) )
  237. {
  238. // The refresher being supplied by the caller is actually
  239. // one of our own refreshers, so a simple cast is convenient
  240. // so that we can access private members.
  241. // =========================================================
  242. CRefresher *pOurRefresher = ( CRefresher * ) pRefresher;
  243. // Add the object to the refresher. The ID is set by AddObject
  244. // ===========================================================
  245. // NB: We are passing a NULL in as the Raw object
  246. hResult = pOurRefresher->AddInstance( pNamespace, pContext, pTemplate, NULL, ppRefreshable, plId );
  247. }
  248. return hResult;
  249. }
  250. STDMETHODIMP CHiPerfProvider::CreateRefreshableEnum(
  251. /* [in] */ IWbemServices* pNamespace,
  252. /* [in, string] */ LPCWSTR wszClass,
  253. /* [in] */ IWbemRefresher* pRefresher,
  254. /* [in] */ long lFlags,
  255. /* [in] */ IWbemContext* pContext,
  256. /* [in] */ IWbemHiPerfEnum* pHiPerfEnum,
  257. /* [out] */ long* plId )
  258. //////////////////////////////////////////////////////////////////////
  259. //
  260. // Called when an enumerator is being added to a refresher. The
  261. // enumerator will obtain a fresh set of instances of the specified
  262. // class every time that refresh is called.
  263. //
  264. // Parameters:
  265. // pNamespace - A pointer to the relevant namespace.
  266. // wszClass - The class name for the requested enumerator.
  267. // pRefresher - The refresher object for which we will add
  268. // the enumerator
  269. // lFlags - Reserved.
  270. // pContext - Not used here.
  271. // pHiPerfEnum - The enumerator to add to the refresher.
  272. // plId - A provider specified ID for the enumerator.
  273. //
  274. //////////////////////////////////////////////////////////////////////
  275. //ok
  276. {
  277. HRESULT hResult = WBEM_NO_ERROR;
  278. if ( pNamespace == 0 || pRefresher == 0 || pHiPerfEnum == 0 )
  279. hResult = WBEM_E_INVALID_PARAMETER;
  280. // Verify hi-perf class
  281. // =====================
  282. if ( !IsHiPerf( pNamespace, wszClass ) )
  283. hResult = WBEM_E_INVALID_CLASS;
  284. if ( SUCCEEDED( hResult ) )
  285. {
  286. // The refresher being supplied by the caller is actually
  287. // one of our own refreshers, so a simple cast is convenient
  288. // so that we can access private members.
  289. CRefresher *pOurRefresher = (CRefresher *) pRefresher;
  290. // Add the enumerator to the refresher. The ID is generated by AddEnum
  291. // ====================================================================
  292. hResult = pOurRefresher->AddEnum( pNamespace, pContext, wszClass, pHiPerfEnum, plId );
  293. }
  294. return hResult;
  295. }
  296. STDMETHODIMP CHiPerfProvider::StopRefreshing(
  297. /* [in] */ IWbemRefresher __RPC_FAR *pRefresher,
  298. /* [in] */ long lId,
  299. /* [in] */ long lFlags )
  300. //////////////////////////////////////////////////////////////////////
  301. //
  302. // Called whenever a user wants to remove an object from a refresher.
  303. //
  304. // Parameters:
  305. // pRefresher - The refresher object from which we are to
  306. // remove the perf object.
  307. // lId - The ID of the object.
  308. // lFlags - Not used.
  309. //
  310. //////////////////////////////////////////////////////////////////////
  311. //ok
  312. {
  313. HRESULT hResult = WBEM_NO_ERROR;
  314. if ( pRefresher == 0 )
  315. hResult = WBEM_E_INVALID_PARAMETER;
  316. if ( SUCCEEDED( hResult ) )
  317. {
  318. // The refresher being supplied by the caller is actually
  319. // one of our own refreshers, so a simple cast is convenient
  320. // so that we can access private members.
  321. // =========================================================
  322. CRefresher *pOurRefresher = (CRefresher *) pRefresher;
  323. hResult = pOurRefresher->Remove( lId );
  324. }
  325. return hResult;
  326. }
  327. STDMETHODIMP CHiPerfProvider::QueryInstances(
  328. /* [in] */ IWbemServices __RPC_FAR *pNamespace,
  329. /* [string][in] */ WCHAR __RPC_FAR *wszClass,
  330. /* [in] */ long lFlags,
  331. /* [in] */ IWbemContext __RPC_FAR *pCtx,
  332. /* [in] */ IWbemObjectSink __RPC_FAR *pSink )
  333. //////////////////////////////////////////////////////////////////////
  334. //
  335. // Called whenever a complete, fresh list of instances for a given
  336. // class is required. The objects are constructed and sent back to the
  337. // caller through the sink. The sink can be used in-line as here, or
  338. // the call can return and a separate thread could be used to deliver
  339. // the instances to the sink.
  340. //
  341. // Parameters:
  342. // pNamespace - A pointer to the relevant namespace. This
  343. // should not be AddRef'ed.
  344. // wszClass - The class name for which instances are required.
  345. // lFlags - Reserved.
  346. // pCtx - The user-supplied context (not used here).
  347. // pSink - The sink to which to deliver the objects. The objects
  348. // can be delivered synchronously through the duration
  349. // of this call or asynchronously (assuming we
  350. // had a separate thread). A IWbemObjectSink::SetStatus
  351. // call is required at the end of the sequence.
  352. //
  353. //////////////////////////////////////////////////////////////////////
  354. //ok
  355. {
  356. HRESULT hResult = WBEM_NO_ERROR;
  357. if (pNamespace == 0 || wszClass == 0 || pSink == 0)
  358. hResult = WBEM_E_INVALID_PARAMETER;
  359. // Verify hi-perf object
  360. // =====================
  361. if ( !IsHiPerf( pNamespace, wszClass ) )
  362. hResult = WBEM_E_INVALID_CLASS;
  363. if ( SUCCEEDED( hResult ) )
  364. {
  365. IWbemRefresher* pRefresher = NULL;
  366. IWbemConfigureRefresher* pConfig = NULL;
  367. IWbemHiPerfEnum* pHiPerfEnum = NULL;
  368. IWbemObjectAccess** apAccess = NULL;
  369. IWbemClassObject** apObject = NULL;
  370. hResult = CoCreateInstance( CLSID_WbemRefresher,
  371. NULL,
  372. CLSCTX_INPROC_SERVER,
  373. IID_IWbemRefresher,
  374. (void**) &pRefresher );
  375. CReleaseMe rm1(pRefresher);
  376. // Get the refresher configuration interface
  377. // =========================================
  378. if ( SUCCEEDED( hResult ) )
  379. {
  380. hResult = pRefresher->QueryInterface( IID_IWbemConfigureRefresher, (void**)&pConfig );
  381. }
  382. CReleaseMe rm2(pConfig);
  383. if ( SUCCEEDED( hResult ) )
  384. {
  385. ULONG uArraySize = 0,
  386. uObjRet = 0;
  387. long lID = 0;
  388. hResult = pConfig->AddEnum( pNamespace, wszClass, 0, pCtx, &pHiPerfEnum, &lID );
  389. CReleaseMe arHiPerfEnum( pHiPerfEnum );
  390. if ( SUCCEEDED( hResult ) )
  391. {
  392. //
  393. // we needs 2 samples for most of the calculations
  394. //
  395. hResult = pRefresher->Refresh( 0L );
  396. hResult = pRefresher->Refresh( 0L );
  397. }
  398. if ( SUCCEEDED( hResult ) )
  399. {
  400. hResult = pHiPerfEnum->GetObjects( 0L, 0, NULL, &uObjRet );
  401. if ( WBEM_E_BUFFER_TOO_SMALL == hResult )
  402. {
  403. uArraySize = uObjRet;
  404. wmilib::auto_buffer<IWbemObjectAccess*> apAccess( new IWbemObjectAccess*[ uObjRet ]);
  405. if ( NULL != apAccess.get() )
  406. {
  407. hResult = pHiPerfEnum->GetObjects( 0L, uArraySize, apAccess.get(), &uObjRet );
  408. }
  409. else
  410. {
  411. hResult = WBEM_E_OUT_OF_MEMORY;
  412. }
  413. if ( SUCCEEDED( hResult ) )
  414. {
  415. // since IWbemObjectAccess derives from IWbemClassObject cast is OK
  416. hResult = pSink->Indicate( uArraySize, (IWbemClassObject **)apAccess.get() );
  417. for ( ULONG uIndex = 0; uIndex < uArraySize; uIndex++ )
  418. {
  419. apAccess[ uIndex ]->Release();
  420. }
  421. }
  422. }
  423. }
  424. if ( SUCCEEDED( hResult ) )
  425. {
  426. pConfig->Remove( lID , 0 );
  427. }
  428. }
  429. }
  430. pSink->SetStatus(0, hResult, 0, 0);
  431. return hResult;
  432. }
  433. STDMETHODIMP CHiPerfProvider::GetObjects(
  434. /* [in] */ IWbemServices* pNamespace,
  435. /* [in] */ long lNumObjects,
  436. /* [in,size_is(lNumObjects)] */ IWbemObjectAccess** apObj,
  437. /* [in] */ long lFlags,
  438. /* [in] */ IWbemContext* pContext)
  439. //////////////////////////////////////////////////////////////////////
  440. //
  441. // Called when a request is made to provide all instances currently
  442. // being managed by the provider in the specified namespace.
  443. //
  444. // Parameters:
  445. // pNamespace - A pointer to the relevant namespace.
  446. // lNumObjects - The number of instances being returned.
  447. // apObj - The array of instances being returned.
  448. // lFlags - Reserved.
  449. // pContext - Not used here.
  450. //
  451. //////////////////////////////////////////////////////////////////////
  452. //ok
  453. {
  454. // Update objects
  455. // ==============
  456. IWbemRefresher* pRefresher = NULL;
  457. IWbemConfigureRefresher* pConfig = NULL;
  458. wmilib::auto_buffer<IWbemClassObject*> apRefObj(new IWbemClassObject*[lNumObjects]);
  459. if (0 == apRefObj.get())
  460. {
  461. return WBEM_E_OUT_OF_MEMORY;
  462. }
  463. // CoCreate the refresher interface
  464. // ================================
  465. HRESULT hResult = CoCreateInstance( CLSID_WbemRefresher,
  466. NULL,
  467. CLSCTX_INPROC_SERVER,
  468. IID_IWbemRefresher,
  469. (void**) &pRefresher );
  470. CReleaseMe arRefresher( pRefresher );
  471. // Get the refresher configuration interface
  472. // =========================================
  473. if ( SUCCEEDED( hResult ) )
  474. {
  475. hResult = pRefresher->QueryInterface( IID_IWbemConfigureRefresher, (void**)&pConfig );
  476. }
  477. CReleaseMe arConfig( pConfig );
  478. // Get the object data
  479. // ===================
  480. if ( SUCCEEDED( hResult ) )
  481. {
  482. long lIndex = 0,
  483. lID = 0;
  484. // Add all of the requested objects to the refresher
  485. // =================================================
  486. for ( lIndex = 0; SUCCEEDED( hResult ) && lIndex < lNumObjects; lIndex++ )
  487. {
  488. // Verify hi-perf object
  489. if ( !IsHiPerfObj( apObj[ lIndex ] ) )
  490. hResult = WBEM_E_INVALID_CLASS;
  491. #ifdef _VERBOSE
  492. {
  493. _variant_t VarPath;
  494. apObj[lIndex]->Get(L"__RELPATH",0,&VarPath,NULL,NULL);
  495. _variant_t VarName;
  496. apObj[lIndex]->Get(L"Name",0,&VarName,NULL,NULL);
  497. DbgPrintfA(0,"%S %S\n",V_BSTR(&VarPath),V_BSTR(&VarName));
  498. }
  499. #endif
  500. if ( SUCCEEDED( hResult ) )
  501. {
  502. hResult = pConfig->AddObjectByTemplate( pNamespace,
  503. apObj[ lIndex ],
  504. 0,
  505. NULL,
  506. &(apRefObj[ lIndex ]),
  507. &lID );
  508. lID = 0;
  509. }
  510. }
  511. if ( SUCCEEDED( hResult ) )
  512. {
  513. hResult = pRefresher->Refresh( 0L );
  514. hResult = pRefresher->Refresh( 0L );
  515. }
  516. for ( lIndex = 0; SUCCEEDED( hResult ) && lIndex < lNumObjects; lIndex++ )
  517. {
  518. hResult = CopyBlob( apRefObj[lIndex], apObj[lIndex] );
  519. apRefObj[lIndex]->Release();
  520. }
  521. }
  522. return hResult;
  523. }