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.

396 lines
9.0 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. perfobj.c
  5. Abstract:
  6. This file implements an Performance Object that presents
  7. System Object Performance Counters
  8. Created:
  9. Bob Watson 22-Oct-1996
  10. Revision History
  11. --*/
  12. //
  13. // Include Files
  14. //
  15. #include <nt.h>
  16. #include <ntrtl.h>
  17. #include <nturtl.h>
  18. #include <windows.h>
  19. #include <winperf.h>
  20. #include <ntprfctr.h>
  21. #include <perfutil.h>
  22. #include <stdio.h>
  23. #include "perfos.h"
  24. #include "perfosmc.h"
  25. #include "dataobj.h"
  26. DWORD dwObjOpenCount = 0; // count of "Open" threads
  27. // variables local to this module.
  28. static HANDLE hEvent = NULL;
  29. static HANDLE hMutex = NULL;
  30. static HANDLE hSemaphore = NULL;
  31. static HANDLE hSection = NULL;
  32. DWORD APIENTRY
  33. OpenObjectsObject (
  34. LPWSTR lpDeviceNames
  35. )
  36. /*++
  37. Routine Description:
  38. This routine will initialize the data structures used to pass
  39. data back to the registry
  40. Arguments:
  41. Pointer to object ID of each device to be opened (PerfGen)
  42. Return Value:
  43. None.
  44. --*/
  45. {
  46. DWORD status = ERROR_SUCCESS;
  47. LONG_PTR TempHandle = -1;
  48. //
  49. // Since WINLOGON is multi-threaded and will call this routine in
  50. // order to service remote performance queries, this library
  51. // must keep track of how many times it has been opened (i.e.
  52. // how many threads have accessed it). the registry routines will
  53. // limit access to the initialization routine to only one thread
  54. // at a time so synchronization (i.e. reentrancy) should not be
  55. // a problem
  56. //
  57. UNREFERENCED_PARAMETER (lpDeviceNames);
  58. if (dwObjOpenCount == 0) {
  59. // open Eventlog interface
  60. hEvent = CreateEvent(NULL,TRUE,TRUE,NULL);
  61. hSemaphore = CreateSemaphore(NULL,1,256,NULL);
  62. hMutex = CreateMutex(NULL,FALSE,NULL);
  63. hSection = CreateFileMapping((HANDLE)TempHandle,NULL,PAGE_READWRITE,0,8192,NULL);
  64. }
  65. dwObjOpenCount++; // increment OPEN counter
  66. status = ERROR_SUCCESS; // for successful exit
  67. return status;
  68. }
  69. DWORD APIENTRY
  70. CollectObjectsObjectData (
  71. IN OUT LPVOID *lppData,
  72. IN OUT LPDWORD lpcbTotalBytes,
  73. IN OUT LPDWORD lpNumObjectTypes
  74. )
  75. /*++
  76. Routine Description:
  77. This routine will return the data for the system objects object
  78. Arguments:
  79. IN OUT LPVOID *lppData
  80. IN: pointer to the address of the buffer to receive the completed
  81. PerfDataBlock and subordinate structures. This routine will
  82. append its data to the buffer starting at the point referenced
  83. by *lppData.
  84. OUT: points to the first byte after the data structure added by this
  85. routine. This routine updated the value at lppdata after appending
  86. its data.
  87. IN OUT LPDWORD lpcbTotalBytes
  88. IN: the address of the DWORD that tells the size in bytes of the
  89. buffer referenced by the lppData argument
  90. OUT: the number of bytes added by this routine is writted to the
  91. DWORD pointed to by this argument
  92. IN OUT LPDWORD NumObjectTypes
  93. IN: the address of the DWORD to receive the number of objects added
  94. by this routine
  95. OUT: the number of objects added by this routine is writted to the
  96. DWORD pointed to by this argument
  97. Returns:
  98. 0 if successful, else Win 32 error code of failure
  99. --*/
  100. {
  101. DWORD TotalLen; // Length of the total return block
  102. NTSTATUS status;
  103. POBJECTS_DATA_DEFINITION pObjectsDataDefinition;
  104. POBJECTS_COUNTER_DATA pOCD;
  105. POBJECT_TYPE_INFORMATION ObjectInfo;
  106. WCHAR Buffer[ 256 ];
  107. //
  108. // Check for sufficient space for objects data
  109. //
  110. pObjectsDataDefinition = (OBJECTS_DATA_DEFINITION *) *lppData;
  111. TotalLen = sizeof(OBJECTS_DATA_DEFINITION) +
  112. sizeof (OBJECTS_COUNTER_DATA);
  113. TotalLen = QWORD_MULTIPLE (TotalLen);
  114. if ( *lpcbTotalBytes < TotalLen ) {
  115. *lpcbTotalBytes = (DWORD) 0;
  116. *lpNumObjectTypes = (DWORD) 0;
  117. return ERROR_MORE_DATA;
  118. }
  119. //
  120. // Define objects data block
  121. //
  122. memcpy (pObjectsDataDefinition,
  123. &ObjectsDataDefinition,
  124. sizeof(OBJECTS_DATA_DEFINITION));
  125. //
  126. // Format and collect objects data
  127. //
  128. pOCD = (POBJECTS_COUNTER_DATA)&pObjectsDataDefinition[1];
  129. pOCD->CounterBlock.ByteLength = sizeof (OBJECTS_COUNTER_DATA);
  130. ObjectInfo = (POBJECT_TYPE_INFORMATION)Buffer;
  131. status = NtQueryObject( NtCurrentProcess(),
  132. ObjectTypeInformation,
  133. ObjectInfo,
  134. sizeof( Buffer ),
  135. NULL
  136. );
  137. if (NT_SUCCESS(status)) {
  138. pOCD->Processes = ObjectInfo->TotalNumberOfObjects;
  139. } else {
  140. ReportEvent (hEventLog,
  141. EVENTLOG_WARNING_TYPE,
  142. 0,
  143. PERFOS_UNABLE_QUERY_PROCESS_OBJECT_INFO,
  144. NULL,
  145. 0,
  146. sizeof(DWORD),
  147. NULL,
  148. (LPVOID)&status);
  149. pOCD->Processes = 0;
  150. }
  151. status = NtQueryObject( NtCurrentThread(),
  152. ObjectTypeInformation,
  153. ObjectInfo,
  154. sizeof( Buffer ),
  155. NULL
  156. );
  157. if (NT_SUCCESS(status)) {
  158. pOCD->Threads = ObjectInfo->TotalNumberOfObjects;
  159. } else {
  160. ReportEvent (hEventLog,
  161. EVENTLOG_WARNING_TYPE,
  162. 0,
  163. PERFOS_UNABLE_QUERY_THREAD_OBJECT_INFO,
  164. NULL,
  165. 0,
  166. sizeof(DWORD),
  167. NULL,
  168. (LPVOID)&status);
  169. pOCD->Threads = 0;
  170. }
  171. status = NtQueryObject( hEvent,
  172. ObjectTypeInformation,
  173. ObjectInfo,
  174. sizeof( Buffer ),
  175. NULL
  176. );
  177. if (NT_SUCCESS(status)) {
  178. pOCD->Events = ObjectInfo->TotalNumberOfObjects;
  179. } else {
  180. ReportEvent (hEventLog,
  181. EVENTLOG_WARNING_TYPE,
  182. 0,
  183. PERFOS_UNABLE_QUERY_EVENT_OBJECT_INFO,
  184. NULL,
  185. 0,
  186. sizeof(DWORD),
  187. NULL,
  188. (LPVOID)&status);
  189. pOCD->Events = 0;
  190. }
  191. status = NtQueryObject( hSemaphore,
  192. ObjectTypeInformation,
  193. ObjectInfo,
  194. sizeof( Buffer ),
  195. NULL
  196. );
  197. if (NT_SUCCESS(status)) {
  198. pOCD->Semaphores = ObjectInfo->TotalNumberOfObjects;
  199. } else {
  200. ReportEvent (hEventLog,
  201. EVENTLOG_WARNING_TYPE,
  202. 0,
  203. PERFOS_UNABLE_QUERY_SEMAPHORE_OBJECT_INFO,
  204. NULL,
  205. 0,
  206. sizeof(DWORD),
  207. NULL,
  208. (LPVOID)&status);
  209. pOCD->Semaphores = 0;
  210. }
  211. status = NtQueryObject( hMutex,
  212. ObjectTypeInformation,
  213. ObjectInfo,
  214. sizeof( Buffer ),
  215. NULL
  216. );
  217. if (NT_SUCCESS(status)) {
  218. pOCD->Mutexes = ObjectInfo->TotalNumberOfObjects;
  219. } else {
  220. ReportEvent (hEventLog,
  221. EVENTLOG_WARNING_TYPE,
  222. 0,
  223. PERFOS_UNABLE_QUERY_MUTEX_OBJECT_INFO,
  224. NULL,
  225. 0,
  226. sizeof(DWORD),
  227. NULL,
  228. (LPVOID)&status);
  229. pOCD->Mutexes = 0;
  230. }
  231. status = NtQueryObject( hSection,
  232. ObjectTypeInformation,
  233. ObjectInfo,
  234. sizeof( Buffer ),
  235. NULL
  236. );
  237. if (NT_SUCCESS(status)) {
  238. pOCD->Sections = ObjectInfo->TotalNumberOfObjects;
  239. } else {
  240. ReportEvent (hEventLog,
  241. EVENTLOG_WARNING_TYPE,
  242. 0,
  243. PERFOS_UNABLE_QUERY_SECTION_OBJECT_INFO,
  244. NULL,
  245. 0,
  246. sizeof(DWORD),
  247. NULL,
  248. (LPVOID)&status);
  249. pOCD->Sections = 0;
  250. }
  251. *lppData = (LPVOID)&pOCD[1];
  252. // round up buffer to the nearest QUAD WORD
  253. *lppData = ALIGN_ON_QWORD (*lppData);
  254. *lpcbTotalBytes =
  255. pObjectsDataDefinition->ObjectsObjectType.TotalByteLength =
  256. (DWORD)((LPBYTE) *lppData -
  257. (LPBYTE) pObjectsDataDefinition);
  258. *lpNumObjectTypes = 1;
  259. return ERROR_SUCCESS;
  260. }
  261. #pragma warning (disable : 4706)
  262. DWORD APIENTRY
  263. CloseObjectsObject (
  264. )
  265. /*++
  266. Routine Description:
  267. This routine closes the open handles to the Signal Gen counters.
  268. Arguments:
  269. None.
  270. Return Value:
  271. ERROR_SUCCESS
  272. --*/
  273. {
  274. if (dwObjOpenCount > 0) {
  275. dwObjOpenCount--;
  276. if (dwObjOpenCount == 0) { // when this is the last thread...
  277. // close stuff here
  278. if (hEvent != NULL) {
  279. CloseHandle(hEvent);
  280. hEvent = NULL;
  281. }
  282. if (hMutex != NULL) {
  283. CloseHandle(hMutex);
  284. hMutex = NULL;
  285. }
  286. if (hSemaphore != NULL) {
  287. CloseHandle(hSemaphore);
  288. hSemaphore = NULL;
  289. }
  290. if (hSection != NULL) {
  291. CloseHandle(hSection);
  292. hSection = NULL;
  293. }
  294. }
  295. }
  296. return ERROR_SUCCESS;
  297. }
  298. #pragma warning (default : 4706)