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.

499 lines
14 KiB

  1. /*++
  2. Copyright (C) 1998-2001 Microsoft Corporation
  3. Module Name:
  4. Abstract:
  5. History:
  6. --*/
  7. //////////////////////////////////////////////////////////////////////
  8. //
  9. // HiPerfProv.cpp
  10. //
  11. //
  12. //
  13. //////////////////////////////////////////////////////////////////////
  14. #include "precomp.h"
  15. #include <stdio.h>
  16. #include <wbemidl.h>
  17. #include <wbemint.h>
  18. #include "common.h"
  19. #include "HiPerProv.h"
  20. ///////////////////////////////////////////////////////////////////
  21. //
  22. // CHiPerfProvider
  23. //
  24. ///////////////////////////////////////////////////////////////////
  25. CHiPerfProvider::CHiPerfProvider(CLifeControl *pControl) :
  26. CUnk(pControl), m_XProviderInit(this), m_XHiPerfProvider(this), m_XRefresher(this)
  27. //ok
  28. {
  29. LOG("CHiPerfProvider::CHiPerfProvider");
  30. // Initialize internal instance cache to empty
  31. for (int i = 0; i < NUM_SAMPLE_INSTANCES; i++)
  32. m_aInstances[i] = 0;
  33. // Initialize property value handles to zero
  34. m_hName = 0;
  35. }
  36. CHiPerfProvider::~CHiPerfProvider()
  37. //ok
  38. {
  39. LOG("CHiPerfProvider::~CHiPerfProvider");
  40. // Release all the objects which have been added to the array.
  41. for (int i = 0; i < NUM_SAMPLE_INSTANCES; i++)
  42. {
  43. if (m_aInstances[i])
  44. m_aInstances[i]->Release();
  45. }
  46. }
  47. void* CHiPerfProvider::GetInterface(REFIID riid)
  48. //ok
  49. {
  50. if(riid == IID_IWbemProviderInit)
  51. return &m_XProviderInit;
  52. if (riid == IID_IWbemHiPerfProvider)
  53. return &m_XHiPerfProvider;
  54. if (riid == IID_IUnknown)
  55. return &m_XHiPerfProvider;
  56. return NULL;
  57. }
  58. ///////////////////////////////////////////////////////////////////
  59. //
  60. // COM implementations
  61. //
  62. ///////////////////////////////////////////////////////////////////
  63. HRESULT CHiPerfProvider::SetHandles(IWbemClassObject* pSampleClass)
  64. //ok
  65. {
  66. LOG("CHiPerfProvider::SetHandles");
  67. // Get the property handles for the well-known properties in
  68. // this counter type. These property handles are available
  69. // to all nested classes of HiPerfProvider
  70. IWbemObjectAccess *pAccess;
  71. LONG hName = 0;
  72. HRESULT hRes = 0;
  73. BSTR PropName = 0;
  74. hRes = pSampleClass->QueryInterface(IID_IWbemObjectAccess, (LPVOID *)&pAccess);
  75. if (FAILED(hRes))
  76. {
  77. LOGERROR("Could not retrieve the IWbemObjectAccess object");
  78. return hRes;
  79. }
  80. // Name handle
  81. PropName = SysAllocString(L"Name");
  82. hRes = pAccess->GetPropertyHandle(PropName, 0, &hName);
  83. if (FAILED(hRes))
  84. {
  85. LOGERROR("Could not get access handle for Name property");
  86. pAccess->Release();
  87. return hRes;
  88. }
  89. m_hName = hName;
  90. SysFreeString(PropName);
  91. pAccess->Release();
  92. return WBEM_NO_ERROR;
  93. }
  94. STDMETHODIMP CHiPerfProvider::XProviderInit::Initialize(
  95. /* [unique][in] */ LPWSTR wszUser,
  96. /* [in] */ LONG lFlags,
  97. /* [in] */ LPWSTR wszNamespace,
  98. /* [unique][in] */ LPWSTR wszLocale,
  99. /* [in] */ IWbemServices __RPC_FAR *pNamespace,
  100. /* [in] */ IWbemContext __RPC_FAR *pCtx,
  101. /* [in] */ IWbemProviderInitSink __RPC_FAR *pInitSink)
  102. //ok
  103. {
  104. LOG("CHiPerfProvider::XProviderInit::Initialize");
  105. IWbemClassObject *pSampleClass = 0;
  106. IWbemObjectAccess *pAccess = 0;
  107. // Get a copy of our sample class def so that we can create & maintain
  108. // instances of it.
  109. BSTR bstrObject = SysAllocString(SAMPLE_CLASS);
  110. HRESULT hRes = pNamespace->GetObject(bstrObject, 0, pCtx, &pSampleClass, 0);
  111. SysFreeString(bstrObject);
  112. if (FAILED(hRes))
  113. {
  114. LOGERROR("Could not create a sample object");
  115. return hRes;
  116. }
  117. hRes = m_pObject->SetHandles(pSampleClass);
  118. if (FAILED(hRes))
  119. {
  120. pSampleClass->Release();
  121. return hRes;
  122. }
  123. // Precreate 10 instances, and set them up in an array which
  124. // is a member of this C++ class.
  125. //
  126. // We only store the IWbemObjectAccess pointers, since
  127. // we are updating 'well-known' properties and already
  128. // know their names.
  129. for (int i = 0; i < NUM_SAMPLE_INSTANCES; i++)
  130. {
  131. IWbemClassObject *pInst = 0;
  132. hRes = pSampleClass->SpawnInstance(0, &pInst);
  133. if (FAILED(hRes))
  134. {
  135. LOGERROR("Could not spawn an instance of the sample class");
  136. pSampleClass->Release();
  137. return hRes;
  138. }
  139. // Get the IWbemObjectAccess interface and cache it
  140. pInst->QueryInterface(IID_IWbemObjectAccess, (LPVOID *)&pAccess);
  141. pInst->Release();
  142. // Set the instance's name.
  143. WCHAR wcsName[128];
  144. swprintf(wcsName, L"Inst_%d", i);
  145. hRes = pAccess->WritePropertyValue(m_pObject->m_hName, (wcslen(wcsName)+1)*sizeof(wchar_t), (BYTE*)wcsName);
  146. if (FAILED(hRes))
  147. {
  148. LOGERROR("Failed to set name of sample class");
  149. pSampleClass->Release();
  150. pAccess->Release();
  151. return hRes;
  152. }
  153. // Add to the instance array
  154. m_pObject->m_aInstances[i] = pAccess;
  155. }
  156. // We now have all the instances ready to go and all the
  157. // property handles cached. Tell WINMGMT that we're
  158. // ready to start 'providing'.
  159. pInitSink->SetStatus(WBEM_S_INITIALIZED, 0);
  160. pSampleClass->Release();
  161. return NO_ERROR;
  162. }
  163. STDMETHODIMP CHiPerfProvider::XHiPerfProvider::QueryInstances(
  164. /* [in] */ IWbemServices __RPC_FAR *pNamespace,
  165. /* [string][in] */ WCHAR __RPC_FAR *wszClass,
  166. /* [in] */ long lFlags,
  167. /* [in] */ IWbemContext __RPC_FAR *pCtx,
  168. /* [in] */ IWbemObjectSink __RPC_FAR *pSink )
  169. //ok
  170. {
  171. LOG("CHiPerfProvider::XHiPerfProvider::QueryInstances");
  172. HRESULT hRes;
  173. if (pNamespace == 0 || wszClass == 0 || pSink == 0)
  174. return WBEM_E_INVALID_PARAMETER;
  175. for (int i = 0; i < NUM_SAMPLE_INSTANCES; i++)
  176. {
  177. IWbemObjectAccess *pAccess = m_pObject->m_aInstances[i];
  178. // Every object can be access one of two ways. In this case
  179. // we get the 'other' (primary) interface to this same object.
  180. IWbemClassObject *pOtherFormat = 0;
  181. hRes = pAccess->QueryInterface(IID_IWbemClassObject, (LPVOID *) &pOtherFormat);
  182. if (FAILED(hRes))
  183. {
  184. LOGERROR("Could not obtain the IWbemClassObject interface");
  185. return hRes;
  186. }
  187. // Send a copy back to the caller.
  188. pSink->Indicate(1, &pOtherFormat);
  189. pOtherFormat->Release(); // Don't need this any more
  190. }
  191. // Tell WINMGMT we are all finished supplying objects.
  192. pSink->SetStatus(0, WBEM_NO_ERROR, 0, 0);
  193. return NO_ERROR;
  194. }
  195. STDMETHODIMP CHiPerfProvider::XHiPerfProvider::CreateRefresher(
  196. /* [in] */ IWbemServices __RPC_FAR *pNamespace,
  197. /* [in] */ long lFlags,
  198. /* [out] */ IWbemRefresher __RPC_FAR *__RPC_FAR *ppRefresher )
  199. //////////////////////////////////////////////////////////////////////
  200. //
  201. // Called whenever a new refresher is needed by the client.
  202. //
  203. // Parameters:
  204. // <pNamespace> A pointer to the relevant namespace. Not used.
  205. // <lFlags> Not used.
  206. // <ppRefresher> Receives the requested refresher.
  207. //
  208. //////////////////////////////////////////////////////////////////////
  209. //ok
  210. {
  211. LOG("CContinousProvider::XContinousProvider::CreateRefresher");
  212. *ppRefresher = NULL;
  213. return NO_ERROR;
  214. }
  215. STDMETHODIMP CHiPerfProvider::XHiPerfProvider::CreateRefreshableObject(
  216. /* [in] */ IWbemServices __RPC_FAR *pNamespace,
  217. /* [in] */ IWbemObjectAccess __RPC_FAR *pTemplate,
  218. /* [in] */ IWbemRefresher __RPC_FAR *pRefresher,
  219. /* [in] */ long lFlags,
  220. /* [in] */ IWbemContext __RPC_FAR *pContext,
  221. /* [out] */ IWbemObjectAccess __RPC_FAR *__RPC_FAR *ppRefreshable,
  222. /* [out] */ long __RPC_FAR *plId )
  223. //////////////////////////////////////////////////////////////////////
  224. //
  225. // Called whenever a user wants to include an object in a refresher.
  226. //
  227. // Parameters:
  228. // <pNamespace> A pointer to the relevant namespace in WINMGMT.
  229. // <pTemplate> A pointer to a copy of the object which is to be
  230. // added. This object itself cannot be used, as
  231. // it not owned locally.
  232. // <pRefresher> The refresher to which to add the object.
  233. // <lFlags> Not used.
  234. // <pContext> Not used here.
  235. // <ppRefreshable> A pointer to the internal object which was added
  236. // to the refresher.
  237. // <plId> The Object Id (for identification during removal).
  238. //
  239. //////////////////////////////////////////////////////////////////////
  240. //ok
  241. {
  242. LOG("CHiPerfProvider::XHiPerfProvider::CreateRefreshableObject");
  243. // Find out which object is being requested for addition.
  244. wchar_t wcsBuf[128];
  245. *wcsBuf = 0;
  246. LONG lNameLength = 0;
  247. pTemplate->ReadPropertyValue(m_pObject->m_hName, (wcslen(wcsBuf)+1)*sizeof(wchar_t), &lNameLength, LPBYTE(wcsBuf));
  248. // Scan out the index from the instance name. We only do this
  249. // because the instance name is a string.
  250. DWORD dwIndex = 0;
  251. swscanf(wcsBuf, L"Inst_%u", &dwIndex);
  252. // Now we know which object is desired.
  253. IWbemObjectAccess *pOurCopy = m_pObject->m_aInstances[dwIndex];
  254. pOurCopy->ReadPropertyValue(m_pObject->m_hName, 128, &lNameLength, LPBYTE(wcsBuf));
  255. char szbuf[256];
  256. wcstombs(szbuf, wcsBuf, 127);
  257. LOG(szbuf);
  258. // The refresher being supplied by the caller is actually
  259. // one of our own refreshers, so a simple cast is convenient
  260. // so that we can access private members.
  261. XRefresher *pOurRefresher;
  262. if (pRefresher)
  263. {
  264. LOG ("NON-NULL refresher");
  265. pOurRefresher = (XRefresher *) pRefresher;
  266. }
  267. else
  268. {
  269. LOG ("NULL refresher");
  270. pOurRefresher = &m_pObject->m_XRefresher;
  271. }
  272. if(pOurRefresher)
  273. pOurRefresher->AddObject(pOurCopy, plId);
  274. // Return a copy of the internal object.
  275. pOurCopy->AddRef();
  276. *ppRefreshable = pOurCopy;
  277. *plId = LONG(dwIndex);
  278. return NO_ERROR;
  279. }
  280. STDMETHODIMP CHiPerfProvider::XHiPerfProvider::StopRefreshing(
  281. /* [in] */ IWbemRefresher __RPC_FAR *pRefresher,
  282. /* [in] */ long lId,
  283. /* [in] */ long lFlags )
  284. //////////////////////////////////////////////////////////////////////
  285. //
  286. // Called whenever a user wants to remove an object from a refresher.
  287. //
  288. // Parameters:
  289. // <pRefresher> The refresher object from which we are to
  290. // remove the perf object.
  291. // <lId> The ID of the object.
  292. // <lFlags> Not used.
  293. //
  294. //////////////////////////////////////////////////////////////////////
  295. //ok
  296. {
  297. LOG("CHiPerfProvider::XHiPerfProvider::StopRefreshing");
  298. // The refresher being supplied by the caller is actually
  299. // one of our own refreshers, so a simple cast is convenient
  300. // so that we can access private members.
  301. XRefresher *pOurRefresher;
  302. if (pRefresher)
  303. {
  304. LOG ("NON-NULL refresher");
  305. pOurRefresher = (XRefresher *) pRefresher;
  306. }
  307. else
  308. {
  309. LOG ("NULL refresher");
  310. pOurRefresher = &m_pObject->m_XRefresher;
  311. }
  312. pOurRefresher->RemoveObject(lId);
  313. return NO_ERROR;
  314. }
  315. STDMETHODIMP CHiPerfProvider::XHiPerfProvider::CreateRefreshableEnum(
  316. /* [in] */ IWbemServices* pNamespace,
  317. /* [in, string] */ LPCWSTR wszClass,
  318. /* [in] */ IWbemRefresher* pRefresher,
  319. /* [in] */ long lFlags,
  320. /* [in] */ IWbemContext* pContext,
  321. /* [in] */ IWbemHiPerfEnum* pHiPerfEnum,
  322. /* [out] */ long* plId )
  323. {
  324. // Just a placeholder for now
  325. LOG("CHiPerfProvider::XHiPerfProvider::CreateRefreshableEnum");
  326. return E_NOTIMPL;
  327. }
  328. STDMETHODIMP CHiPerfProvider::XHiPerfProvider::GetObjects(
  329. /* [in] */ IWbemServices* pNamespace,
  330. /* [in] */ long lNumObjects,
  331. /* [in,size_is(lNumObjects)] */ IWbemObjectAccess** apObj,
  332. /* [in] */ long lFlags,
  333. /* [in] */ IWbemContext* pContext)
  334. {
  335. // Just a placeholder for now
  336. LOG("CHiPerfProvider::XHiPerfProvider::GetObjects");
  337. return E_NOTIMPL;
  338. }
  339. CHiPerfProvider::XRefresher::XRefresher(CHiPerfProvider *pObject) :
  340. CImpl<IWbemRefresher, CHiPerfProvider>(pObject)
  341. //ok
  342. {
  343. LOG("CHiPerfProvider::XRefresher::XRefresher");
  344. // Initialize the instance cache to be empty
  345. for (int i = 0; i < NUM_SAMPLE_INSTANCES; i++)
  346. m_aRefInstances[i] = 0;
  347. }
  348. CHiPerfProvider::XRefresher::~XRefresher()
  349. //ok
  350. {
  351. LOG("CHiPerfProvider::XRefresher::~XRefresher");
  352. // Release the cached IWbemObjectAccess instances.
  353. for (DWORD i = 0; i < NUM_SAMPLE_INSTANCES; i++)
  354. {
  355. if (m_aRefInstances[i])
  356. m_aRefInstances[i]->Release();
  357. }
  358. }
  359. BOOL CHiPerfProvider::XRefresher::AddObject(IWbemObjectAccess *pObj, LONG *plId)
  360. //////////////////////////////////////////////////////////////////////
  361. //
  362. // Adds an object to the refresher. This is a private mechanism
  363. // used by CHiPerfProvider and not part of the COM interface.
  364. //
  365. // The ID we return for future identification is simply
  366. // the array index.
  367. //
  368. //////////////////////////////////////////////////////////////////////
  369. //ok
  370. {
  371. LOG("CHiPerfProvider::XRefresher::AddObject");
  372. for (DWORD i = 0; i < NUM_SAMPLE_INSTANCES; i++)
  373. {
  374. if (m_aRefInstances[i] == 0)
  375. {
  376. pObj->AddRef();
  377. m_aRefInstances[i] = pObj;
  378. // The ID we return for future identification is simply
  379. // the array index.
  380. *plId = i;
  381. LOG("Added Object");
  382. return TRUE;
  383. }
  384. }
  385. LOGERROR("Failed to Add Object");
  386. return FALSE;
  387. }
  388. BOOL CHiPerfProvider::XRefresher::RemoveObject(LONG lId)
  389. //////////////////////////////////////////////////////////////////////
  390. //
  391. // Removes an object from the refresher. This is a private mechanism
  392. // used by CHiPerfProvider and not part of the COM interface.
  393. //
  394. // Removes an object from the refresher by ID. In our case, the ID
  395. // is actually the array index we used internally, so it is simple
  396. // to locate and remove the object.
  397. //
  398. //////////////////////////////////////////////////////////////////////
  399. //ok
  400. {
  401. LOG("CHiPerfProvider::XRefresher::RemoveObject");
  402. if (m_aRefInstances[lId] == 0)
  403. return FALSE;
  404. m_aRefInstances[lId]->Release();
  405. m_aRefInstances[lId] = 0;
  406. return TRUE;
  407. }
  408. HRESULT CHiPerfProvider::XRefresher::Refresh(/* [in] */ long lFlags)
  409. //////////////////////////////////////////////////////////////////////
  410. //
  411. // Executed to refresh a set of instances bound to the particular
  412. // refresher.
  413. //
  414. //////////////////////////////////////////////////////////////////////
  415. //ok
  416. {
  417. LOG("CHiPerfProvider::XRefresher::Refresh");
  418. return NO_ERROR;
  419. }