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.

424 lines
10 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. HANDLE hEvent = NULL;
  29. HANDLE hMutex = NULL;
  30. HANDLE hSemaphore = NULL;
  31. 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. #ifdef DBG
  108. STARTTIMING;
  109. #endif
  110. //
  111. // Check for sufficient space for objects data
  112. //
  113. pObjectsDataDefinition = (OBJECTS_DATA_DEFINITION *) *lppData;
  114. TotalLen = sizeof(OBJECTS_DATA_DEFINITION) +
  115. sizeof (OBJECTS_COUNTER_DATA);
  116. TotalLen = QWORD_MULTIPLE (TotalLen);
  117. if ( *lpcbTotalBytes < TotalLen ) {
  118. *lpcbTotalBytes = (DWORD) 0;
  119. *lpNumObjectTypes = (DWORD) 0;
  120. return ERROR_MORE_DATA;
  121. }
  122. //
  123. // Define objects data block
  124. //
  125. memcpy (pObjectsDataDefinition,
  126. &ObjectsDataDefinition,
  127. sizeof(OBJECTS_DATA_DEFINITION));
  128. //
  129. // Format and collect objects data
  130. //
  131. pOCD = (POBJECTS_COUNTER_DATA)&pObjectsDataDefinition[1];
  132. pOCD->CounterBlock.ByteLength = QWORD_MULTIPLE(sizeof (OBJECTS_COUNTER_DATA));
  133. ObjectInfo = (POBJECT_TYPE_INFORMATION)Buffer;
  134. status = NtQueryObject( NtCurrentProcess(),
  135. ObjectTypeInformation,
  136. ObjectInfo,
  137. sizeof( Buffer ),
  138. NULL
  139. );
  140. if (NT_SUCCESS(status)) {
  141. pOCD->Processes = ObjectInfo->TotalNumberOfObjects;
  142. } else {
  143. if (hEventLog != NULL) {
  144. ReportEvent (hEventLog,
  145. EVENTLOG_WARNING_TYPE,
  146. 0,
  147. PERFOS_UNABLE_QUERY_PROCESS_OBJECT_INFO,
  148. NULL,
  149. 0,
  150. sizeof(DWORD),
  151. NULL,
  152. (LPVOID)&status);
  153. }
  154. pOCD->Processes = 0;
  155. }
  156. #ifdef DBG
  157. ENDTIMING (("PERFOBJ: %d takes %I64u ms\n", __LINE__, diff));
  158. #endif
  159. status = NtQueryObject( NtCurrentThread(),
  160. ObjectTypeInformation,
  161. ObjectInfo,
  162. sizeof( Buffer ),
  163. NULL
  164. );
  165. if (NT_SUCCESS(status)) {
  166. pOCD->Threads = ObjectInfo->TotalNumberOfObjects;
  167. } else {
  168. if (hEventLog != NULL) {
  169. ReportEvent (hEventLog,
  170. EVENTLOG_WARNING_TYPE,
  171. 0,
  172. PERFOS_UNABLE_QUERY_THREAD_OBJECT_INFO,
  173. NULL,
  174. 0,
  175. sizeof(DWORD),
  176. NULL,
  177. (LPVOID)&status);
  178. }
  179. pOCD->Threads = 0;
  180. }
  181. #ifdef DBG
  182. ENDTIMING (("PERFOBJ: %d takes %I64u ms\n", __LINE__, diff));
  183. #endif
  184. status = NtQueryObject( hEvent,
  185. ObjectTypeInformation,
  186. ObjectInfo,
  187. sizeof( Buffer ),
  188. NULL
  189. );
  190. if (NT_SUCCESS(status)) {
  191. pOCD->Events = ObjectInfo->TotalNumberOfObjects;
  192. } else {
  193. if (hEventLog != NULL) {
  194. ReportEvent (hEventLog,
  195. EVENTLOG_WARNING_TYPE,
  196. 0,
  197. PERFOS_UNABLE_QUERY_EVENT_OBJECT_INFO,
  198. NULL,
  199. 0,
  200. sizeof(DWORD),
  201. NULL,
  202. (LPVOID)&status);
  203. }
  204. pOCD->Events = 0;
  205. }
  206. #ifdef DBG
  207. ENDTIMING (("PERFOBJ: %d takes %I64u ms\n", __LINE__, diff));
  208. #endif
  209. status = NtQueryObject( hSemaphore,
  210. ObjectTypeInformation,
  211. ObjectInfo,
  212. sizeof( Buffer ),
  213. NULL
  214. );
  215. if (NT_SUCCESS(status)) {
  216. pOCD->Semaphores = ObjectInfo->TotalNumberOfObjects;
  217. } else {
  218. if (hEventLog != NULL) {
  219. ReportEvent (hEventLog,
  220. EVENTLOG_WARNING_TYPE,
  221. 0,
  222. PERFOS_UNABLE_QUERY_SEMAPHORE_OBJECT_INFO,
  223. NULL,
  224. 0,
  225. sizeof(DWORD),
  226. NULL,
  227. (LPVOID)&status);
  228. }
  229. pOCD->Semaphores = 0;
  230. }
  231. #ifdef DBG
  232. ENDTIMING (("PERFOBJ: %d takes %I64u ms\n", __LINE__, diff));
  233. #endif
  234. status = NtQueryObject( hMutex,
  235. ObjectTypeInformation,
  236. ObjectInfo,
  237. sizeof( Buffer ),
  238. NULL
  239. );
  240. if (NT_SUCCESS(status)) {
  241. pOCD->Mutexes = ObjectInfo->TotalNumberOfObjects;
  242. } else {
  243. if (hEventLog != NULL) {
  244. ReportEvent (hEventLog,
  245. EVENTLOG_WARNING_TYPE,
  246. 0,
  247. PERFOS_UNABLE_QUERY_MUTEX_OBJECT_INFO,
  248. NULL,
  249. 0,
  250. sizeof(DWORD),
  251. NULL,
  252. (LPVOID)&status);
  253. }
  254. pOCD->Mutexes = 0;
  255. }
  256. #ifdef DBG
  257. ENDTIMING (("PERFOBJ: %d takes %I64u ms\n", __LINE__, diff));
  258. #endif
  259. status = NtQueryObject( hSection,
  260. ObjectTypeInformation,
  261. ObjectInfo,
  262. sizeof( Buffer ),
  263. NULL
  264. );
  265. if (NT_SUCCESS(status)) {
  266. pOCD->Sections = ObjectInfo->TotalNumberOfObjects;
  267. } else {
  268. if (hEventLog != NULL) {
  269. ReportEvent (hEventLog,
  270. EVENTLOG_WARNING_TYPE,
  271. 0,
  272. PERFOS_UNABLE_QUERY_SECTION_OBJECT_INFO,
  273. NULL,
  274. 0,
  275. sizeof(DWORD),
  276. NULL,
  277. (LPVOID)&status);
  278. }
  279. pOCD->Sections = 0;
  280. }
  281. *lpcbTotalBytes =
  282. pObjectsDataDefinition->ObjectsObjectType.TotalByteLength =
  283. (DWORD) QWORD_MULTIPLE(((LPBYTE) (& pOCD[1])) -
  284. (LPBYTE) pObjectsDataDefinition);
  285. * lppData = (LPVOID) (((LPBYTE) pObjectsDataDefinition) + * lpcbTotalBytes);
  286. *lpNumObjectTypes = 1;
  287. #ifdef DBG
  288. ENDTIMING (("PERFOBJ: %d takes %I64u ms\n", __LINE__, diff));
  289. #endif
  290. return ERROR_SUCCESS;
  291. }
  292. DWORD APIENTRY
  293. CloseObjectsObject (
  294. )
  295. /*++
  296. Routine Description:
  297. This routine closes the open handles to the Signal Gen counters.
  298. Arguments:
  299. None.
  300. Return Value:
  301. ERROR_SUCCESS
  302. --*/
  303. {
  304. if (dwObjOpenCount > 0) {
  305. dwObjOpenCount--;
  306. if (dwObjOpenCount == 0) { // when this is the last thread...
  307. // close stuff here
  308. if (hEvent != NULL) {
  309. CloseHandle(hEvent);
  310. hEvent = NULL;
  311. }
  312. if (hMutex != NULL) {
  313. CloseHandle(hMutex);
  314. hMutex = NULL;
  315. }
  316. if (hSemaphore != NULL) {
  317. CloseHandle(hSemaphore);
  318. hSemaphore = NULL;
  319. }
  320. if (hSection != NULL) {
  321. CloseHandle(hSection);
  322. hSection = NULL;
  323. }
  324. }
  325. }
  326. return ERROR_SUCCESS;
  327. }