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.

554 lines
14 KiB

  1. /*++
  2. Copyright (c) 1998-1999 Microsoft Corporation
  3. Module Name:
  4. ulperf.cpp
  5. Abstract:
  6. This is the main code for the ul.sys performance counter support object
  7. Author:
  8. Paul McDaniel (paulmcd) 11-May-1999
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #include "ulperf.h"
  13. //
  14. // Globals
  15. //
  16. LONG g_lInit;
  17. HINSTANCE g_hInstance;
  18. //
  19. // Active "opens" reference count for Open/Close PerformanceData
  20. //
  21. ULONG OpenCount = 0;
  22. //
  23. // An open handle to the event log for error logging
  24. //
  25. HANDLE hEventLog;
  26. //
  27. // Initialize the constant portions of the HKEY_PERFORMANCE data structure.
  28. // Certain parts (especially the name/help indices) will be
  29. // updated at initialization time.
  30. //
  31. const UL_COUNTER_BLOCK CounterBlock;
  32. UL_PERF_OBJECT_DEFINITION ObjectDefinition =
  33. {
  34. { // ObjectType
  35. sizeof(UL_PERF_OBJECT_DEFINITION) + sizeof(UL_COUNTER_BLOCK),
  36. sizeof(UL_PERF_OBJECT_DEFINITION),
  37. sizeof(PERF_OBJECT_TYPE),
  38. UL_COUNTER_OBJECT,
  39. NULL,
  40. UL_COUNTER_OBJECT,
  41. NULL,
  42. PERF_DETAIL_ADVANCED,
  43. NUMBER_OF_UL_COUNTERS,
  44. -1, // DefaultCounter
  45. PERF_NO_INSTANCES,
  46. 0,
  47. { 0, 0 },
  48. { 0, 0 }
  49. },
  50. { // BytesSent
  51. sizeof(PERF_COUNTER_DEFINITION),
  52. UL_BYTES_SENT_COUNTER,
  53. NULL, // assigned in OpenPerformanceData()
  54. UL_BYTES_SENT_COUNTER,
  55. NULL, // assigned in OpenPerformanceData()
  56. 0,
  57. PERF_DETAIL_ADVANCED,
  58. PERF_COUNTER_COUNTER,
  59. 0, // assigned in OpenPerformanceData()
  60. 0 // assigned in OpenPerformanceData()
  61. },
  62. { // BytesReceived
  63. sizeof(PERF_COUNTER_DEFINITION),
  64. UL_BYTES_RECEIVED_COUNTER,
  65. NULL,
  66. UL_BYTES_RECEIVED_COUNTER,
  67. NULL,
  68. 0,
  69. PERF_DETAIL_ADVANCED,
  70. PERF_COUNTER_COUNTER,
  71. 0,
  72. 0
  73. },
  74. { // CurrentConnections
  75. sizeof(PERF_COUNTER_DEFINITION),
  76. UL_CURRENT_CONNECTIONS_NUMBER,
  77. NULL,
  78. UL_CURRENT_CONNECTIONS_NUMBER,
  79. NULL,
  80. 0,
  81. PERF_DETAIL_ADVANCED,
  82. PERF_COUNTER_RAWCOUNT,
  83. 0,
  84. 0
  85. },
  86. { // CurrentRequests
  87. sizeof(PERF_COUNTER_DEFINITION),
  88. UL_CURRENT_REQUESTS_NUMBER,
  89. NULL,
  90. UL_CURRENT_REQUESTS_NUMBER,
  91. NULL,
  92. 0,
  93. PERF_DETAIL_ADVANCED,
  94. PERF_COUNTER_RAWCOUNT,
  95. 0,
  96. 0
  97. },
  98. { // QueuedRequests
  99. sizeof(PERF_COUNTER_DEFINITION),
  100. UL_QUEUED_REQUESTS_NUMBER,
  101. NULL,
  102. UL_QUEUED_REQUESTS_NUMBER,
  103. NULL,
  104. 0,
  105. PERF_DETAIL_ADVANCED,
  106. PERF_COUNTER_RAWCOUNT,
  107. 0,
  108. 0
  109. },
  110. { // AttachedProcesses
  111. sizeof(PERF_COUNTER_DEFINITION),
  112. UL_ATTACHED_PROCESSES_NUMBER,
  113. NULL,
  114. UL_ATTACHED_PROCESSES_NUMBER,
  115. NULL,
  116. 0,
  117. PERF_DETAIL_ADVANCED,
  118. PERF_COUNTER_RAWCOUNT,
  119. 0,
  120. 0
  121. }
  122. };
  123. DWORD
  124. OpenPerformanceData(
  125. LPWSTR lpDeviceNames
  126. )
  127. {
  128. DWORD Error = NO_ERROR;
  129. HKEY hkey = NULL;
  130. DWORD size;
  131. DWORD type;
  132. DWORD dwFirstCounter;
  133. DWORD dwFirstHelp;
  134. DWORD i;
  135. PERF_COUNTER_DEFINITION * pctr;
  136. //
  137. // Since WINLOGON is multi-threaded and will call this routine in
  138. // order to service remote performance queries, this library
  139. // must keep track of how many times it has been opened (i.e.
  140. // how many threads have accessed it). The registry routines will
  141. // limit access to the initialization routine to only one thread
  142. // at a time so synchronization (i.e. reentrancy) should not be
  143. // a problem.
  144. //
  145. if (OpenCount == 0)
  146. {
  147. //
  148. // This is the *first* open.
  149. //
  150. // open event log interface
  151. if (hEventLog == NULL)
  152. {
  153. hEventLog = RegisterEventSource(
  154. (LPTSTR)NULL, // Use Local Machine
  155. APP_NAME // event log app name
  156. // to find in registry
  157. );
  158. }
  159. //
  160. // open the performance key
  161. //
  162. Error = RegOpenKeyEx(
  163. HKEY_LOCAL_MACHINE,
  164. REGISTRY_UL_INFORMATION L"\\Performance",
  165. 0,
  166. KEY_ALL_ACCESS,
  167. &hkey
  168. );
  169. if( err == NO_ERROR )
  170. {
  171. //
  172. // Read the first counter DWORD.
  173. //
  174. size = sizeof(DWORD);
  175. err = RegQueryValueEx(
  176. hkey,
  177. L"First Counter",
  178. NULL,
  179. &type,
  180. (LPBYTE)&dwFirstCounter,
  181. &size
  182. );
  183. if( err == NO_ERROR )
  184. {
  185. //
  186. // Read the first help DWORD.
  187. //
  188. size = sizeof(DWORD);
  189. err = RegQueryValueEx( hkey,
  190. L"First Help",
  191. NULL,
  192. &type,
  193. (LPBYTE)&dwFirstHelp,
  194. &size );
  195. if ( err == NO_ERROR )
  196. {
  197. //
  198. // Update the object & counter name & help indicies.
  199. //
  200. ObjectDefinition.ObjectType.ObjectNameTitleIndex
  201. += dwFirstCounter;
  202. ObjectDefinition.ObjectType.ObjectHelpTitleIndex
  203. += dwFirstHelp;
  204. #define ADJUST_VALUES(CounterName) \
  205. do {\
  206. ObjectDefinition.##CounterName.CounterNameTitleIndex \
  207. += dwFirstCounter; \
  208. ObjectDefinition.##CounterName.CounterHelpTitleIndex \
  209. += dwFirstHelp; \
  210. ObjectDefinition.##CounterName.CounterSize \
  211. = sizeof(CounterBlock.##CounterName); \
  212. ObjectDefinition.##CounterName.CounterOffset = \
  213. DIFF((LPBYTE)&CounterBlock.##CounterName - (LPBYTE)&CounterBlock);\
  214. } while (0)
  215. ADJUST_VALUES(BytesSent);
  216. ADJUST_VALUES(BytesReceived);
  217. ADJUST_VALUES(CurrentConnections);
  218. ADJUST_VALUES(CurrentRequests);
  219. ADJUST_VALUES(QueuedRequests);
  220. ADJUST_VALUES(AttachedProcesses);
  221. //
  222. // Remember that we initialized OK.
  223. //
  224. fInitOK = TRUE;
  225. } else {
  226. ReportEvent (hEventLog, EVENTLOG_ERROR_TYPE,
  227. 0, W3_UNABLE_READ_FIRST_HELP,
  228. (PSID)NULL, 0,
  229. sizeof(err), NULL,
  230. (PVOID)(&err));
  231. }
  232. } else {
  233. ReportEvent (hEventLog, EVENTLOG_ERROR_TYPE,
  234. 0, W3_UNABLE_READ_FIRST_COUNTER,
  235. (PSID)NULL, 0,
  236. sizeof(err), NULL,
  237. (PVOID)(&err));
  238. }
  239. //
  240. // Close the registry if we managed to actually open it.
  241. //
  242. if( hkey != NULL )
  243. {
  244. RegCloseKey( hkey );
  245. hkey = NULL;
  246. }
  247. } else {
  248. ReportEvent (hEventLog, EVENTLOG_ERROR_TYPE,
  249. 0, W3_UNABLE_OPEN_W3SVC_PERF_KEY,
  250. (PSID)NULL, 0,
  251. sizeof(err), NULL,
  252. (PVOID)(&err));
  253. }
  254. }
  255. //
  256. // Bump open counter.
  257. //
  258. OpenCount += 1;
  259. end:
  260. return Error;
  261. } // OpenPerformanceData
  262. DWORD
  263. CollectPerformanceData(
  264. LPWSTR lpwszValue,
  265. LPVOID *lppData,
  266. LPDWORD lpcbBytes,
  267. LPDWORD lpcObjectTypes
  268. )
  269. {
  270. }
  271. DWORD
  272. WINAPI
  273. ClosePerformanceData(
  274. )
  275. {
  276. //
  277. // Clean up
  278. //
  279. OpenCount -= 1;
  280. if (OpenCount == 0)
  281. {
  282. if (hEventLog != NULL)
  283. {
  284. DeregisterEventSource(hEventLog);
  285. hEventLog = NULL;
  286. }
  287. }
  288. return NO_ERROR;
  289. } // ClosePerformanceData
  290. CUlPerfCounters::CUlPerfCounters()
  291. {
  292. }
  293. CUlPerfCounters::~CUlPerfCounters()
  294. {
  295. }
  296. //
  297. // IWbemProviderInit
  298. //
  299. STDMETHODIMP CUlPerfCounters::Initialize(LPWSTR wszUser,LONG lFlags,LPWSTR wszNamespace,LPWSTR wszLocale,IWbemServices* pNamespace,IWbemContext* pCtx,IWbemProviderInitSink* pInitSink)
  300. {
  301. HRESULT Result;
  302. ASSERT(pInitSink != NULL);
  303. TRACE(L"ulperf!CUlPerfCounters::Initialize called\n");
  304. //
  305. // tell wbem we are ready to go.
  306. //
  307. Result = pInitSink->SetStatus(WBEM_S_INITIALIZED, 0);
  308. return Result;
  309. } // CUlPerfCounters::Initialize
  310. //
  311. // IWbemServices
  312. //
  313. // Context.
  314. // ========
  315. STDMETHODIMP CUlPerfCounters::OpenNamespace(BSTR strNamespace, long lFlags, IWbemContext* pCtx, IWbemServices** ppWorkingNamespace, IWbemCallResult** ppResult)
  316. { return WBEM_E_METHOD_NOT_IMPLEMENTED; }
  317. STDMETHODIMP CUlPerfCounters::CancelAsyncCall(IWbemObjectSink* pSink)
  318. { return WBEM_E_METHOD_NOT_IMPLEMENTED; }
  319. STDMETHODIMP CUlPerfCounters::QueryObjectSink(long lFlags,IWbemObjectSink** ppResponseHandler)
  320. { return WBEM_E_METHOD_NOT_IMPLEMENTED; }
  321. // Classes and instances.
  322. // ======================
  323. STDMETHODIMP CUlPerfCounters::GetObject(BSTR strObjectPath,long lFlags,IWbemContext* pCtx,IWbemClassObject** ppObject,IWbemCallResult** ppCallResult)
  324. { return WBEM_E_METHOD_NOT_IMPLEMENTED; }
  325. STDMETHODIMP CUlPerfCounters::GetObjectAsync(BSTR strObjectPath,long lFlags,IWbemContext* pCtx,IWbemObjectSink* pResponseHandler)
  326. {
  327. IWbemClassObject pObj;
  328. HRESULT Result;
  329. CObjectPathParser PathParser;
  330. ParsedObjectPath *pParsedPath = NULL;
  331. Result = WBEM_S_NO_ERROR;
  332. //
  333. // crack the object path
  334. //
  335. Result = PathParser.Parse(strObjectPath, &pParsedPath);
  336. if (Result != CObjectPathParser::NoError)
  337. return E_FAIL;
  338. //
  339. // create a perfctr object
  340. //
  341. pObject = new CComObject<CUlPerfCounterObject>;
  342. if (pObject == NULL)
  343. {
  344. Result = E_OUTOFMEMORY
  345. goto end;
  346. }
  347. //
  348. // init it
  349. //
  350. Result = pObject->Init(pParsedPath);
  351. if (FAILED(Result))
  352. goto end;
  353. //
  354. // and hand it off to wbem
  355. //
  356. Result = pGroup->_InternalQueryInterface(IID_IWbemClassObject, (PVOID*)&pWbemObj);
  357. if (FAILED(Result))
  358. goto end;
  359. Result = pHandler->Indicate(1, &pWbemObj);
  360. if (FAILED(Result))
  361. goto end;
  362. end:
  363. if (pParsedPath != NULL)
  364. {
  365. PathParser.Free(pParsedPath);
  366. pParsedPath = NULL;
  367. }
  368. if (pWbemObj != NULL)
  369. {
  370. pWbemObj->Release();
  371. pWbemObj = NULL;
  372. }
  373. pHandler->SetStatus(0, Result, NULL, NULL);
  374. return Result;
  375. }
  376. // Class manipulation.
  377. // ===================
  378. STDMETHODIMP CUlPerfCounters::PutClass(IWbemClassObject* pObject,long lFlags,IWbemContext* pCtx,IWbemCallResult** ppCallResult)
  379. { return WBEM_E_METHOD_NOT_IMPLEMENTED; }
  380. STDMETHODIMP CUlPerfCounters::PutClassAsync(IWbemClassObject* pObject,long lFlags,IWbemContext* pCtx,IWbemObjectSink* pResponseHandler)
  381. { return WBEM_E_METHOD_NOT_IMPLEMENTED; }
  382. STDMETHODIMP CUlPerfCounters::DeleteClass(BSTR strClass,long lFlags,IWbemContext* pCtx,IWbemCallResult** ppCallResult)
  383. { return WBEM_E_METHOD_NOT_IMPLEMENTED; }
  384. STDMETHODIMP CUlPerfCounters::DeleteClassAsync(BSTR strClass,long lFlags,IWbemContext* pCtx,IWbemObjectSink* pResponseHandler)
  385. { return WBEM_E_METHOD_NOT_IMPLEMENTED; }
  386. STDMETHODIMP CUlPerfCounters::CreateClassEnum(BSTR strSuperclass,long lFlags,IWbemContext* pCtx,IEnumWbemClassObject** ppEnum)
  387. { return WBEM_E_METHOD_NOT_IMPLEMENTED; }
  388. STDMETHODIMP CUlPerfCounters::CreateClassEnumAsync(BSTR strSuperclass,long lFlags,IWbemContext* pCtx,IWbemObjectSink* pResponseHandler)
  389. { return WBEM_E_METHOD_NOT_IMPLEMENTED; }
  390. // Instances.
  391. // ==========
  392. STDMETHODIMP CUlPerfCounters::PutInstance(IWbemClassObject* pInst,long lFlags,IWbemContext* pCtx,IWbemCallResult** ppCallResult)
  393. { return WBEM_E_METHOD_NOT_IMPLEMENTED; }
  394. STDMETHODIMP CUlPerfCounters::PutInstanceAsync(IWbemClassObject* pInst,long lFlags,IWbemContext* pCtx,IWbemObjectSink* pResponseHandler)
  395. { return WBEM_E_METHOD_NOT_IMPLEMENTED; }
  396. STDMETHODIMP CUlPerfCounters::DeleteInstance(BSTR strObjectPath,long lFlags,IWbemContext* pCtx,IWbemCallResult** ppCallResult)
  397. { return WBEM_E_METHOD_NOT_IMPLEMENTED; }
  398. STDMETHODIMP CUlPerfCounters::DeleteInstanceAsync(BSTR strObjectPath,long lFlags,IWbemContext* pCtx,IWbemObjectSink* pResponseHandler)
  399. { return WBEM_E_METHOD_NOT_IMPLEMENTED; }
  400. STDMETHODIMP CUlPerfCounters::CreateInstanceEnum(BSTR strClass,long lFlags,IWbemContext* pCtx,IEnumWbemClassObject** ppEnum)
  401. { return WBEM_E_METHOD_NOT_IMPLEMENTED; }
  402. STDMETHODIMP CUlPerfCounters::CreateInstanceEnumAsync(BSTR strClass,long lFlags,IWbemContext* pCtx,IWbemObjectSink* pResponseHandler)
  403. { return WBEM_E_METHOD_NOT_IMPLEMENTED; }
  404. // Queries.
  405. // ========
  406. STDMETHODIMP CUlPerfCounters::ExecQuery(BSTR strQueryLanguage,BSTR strQuery,long lFlags,IWbemContext* pCtx,IEnumWbemClassObject** ppEnum)
  407. { return WBEM_E_METHOD_NOT_IMPLEMENTED; }
  408. STDMETHODIMP CUlPerfCounters::ExecQueryAsync(BSTR strQueryLanguage,BSTR strQuery,long lFlags,IWbemContext* pCtx,IWbemObjectSink* pResponseHandler)
  409. { return WBEM_E_METHOD_NOT_IMPLEMENTED; }
  410. STDMETHODIMP CUlPerfCounters::ExecNotificationQuery(BSTR strQueryLanguage,BSTR strQuery,long lFlags,IWbemContext* pCtx,IEnumWbemClassObject** ppEnum)
  411. { return WBEM_E_METHOD_NOT_IMPLEMENTED; }
  412. STDMETHODIMP CUlPerfCounters::ExecNotificationQueryAsync(BSTR strQueryLanguage,BSTR strQuery,long lFlags,IWbemContext* pCtx,IWbemObjectSink* pResponseHandler)
  413. { return WBEM_E_METHOD_NOT_IMPLEMENTED; }
  414. // Methods
  415. // =======
  416. STDMETHODIMP CUlPerfCounters::ExecMethod(BSTR strObjectPath,BSTR strMethodName,long lFlags,IWbemContext* pCtx,IWbemClassObject* pInParams,IWbemClassObject** ppOutParams,IWbemCallResult** ppCallResult)
  417. { return WBEM_E_METHOD_NOT_IMPLEMENTED; }
  418. STDMETHODIMP CUlPerfCounters::ExecMethodAsync(BSTR strObjectPath,BSTR strMethodName,long lFlags,IWbemContext* pCtx,IWbemClassObject* pInParams,IWbemObjectSink* pResponseHandler)
  419. { return WBEM_E_METHOD_NOT_IMPLEMENTED; }