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.

371 lines
9.0 KiB

  1. /*++ BUILD Version: 0001 // Increment this if a change has global effects
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. perfsfm.c
  5. Abstract:
  6. This file implements the Extensible Objects for the Sfm object type
  7. Created:
  8. Russ Blake 24 Feb 93
  9. Sue Adams 07 Jun 93
  10. Revision History
  11. Sue Adams 23 Feb 94 - no longer need to open \MacSrv\... registry
  12. key to query for FirstCounter and FirstHelp. These
  13. are now hardcoded values in the base NT system.
  14. SFMOBJ = 1000, SFMOBJ_HELP = 1001
  15. Jameel Hyder Use SFM Apis instead of Nt apis to get the counters.
  16. --*/
  17. //
  18. // Include Files
  19. //
  20. #include <nt.h>
  21. #include <ntrtl.h>
  22. #include <nturtl.h>
  23. #include <windows.h>
  24. #include <string.h>
  25. #include <wcstr.h>
  26. #include <winperf.h>
  27. #include "sfmctrs.h" // error message definition
  28. #include "perfmsg.h"
  29. #include "perfutil.h"
  30. #include "datasfm.h"
  31. #include <macfile.h>
  32. #include <admin.h>
  33. //
  34. // References to constants which initialize the Object type definitions
  35. // (see datasfm.h & .c)
  36. //
  37. extern SFM_DATA_DEFINITION SfmDataDefinition;
  38. DWORD dwOpenCount = 0; // count of "Open" threads
  39. BOOL bInitOK = FALSE; // true = DLL initialized OK
  40. //
  41. // Sfm data structures
  42. //
  43. PPERF_COUNTER_BLOCK pCounterBlock;
  44. AFP_SERVER_HANDLE SfmRpcHandle;
  45. //
  46. // Function Prototypes
  47. //
  48. // these are used to insure that the data collection functions
  49. // accessed by Perflib will have the correct calling format.
  50. //
  51. PM_OPEN_PROC OpenAfpPerformanceData;
  52. PM_COLLECT_PROC CollectAfpPerformanceData;
  53. PM_CLOSE_PROC CloseAfpPerformanceData;
  54. DWORD
  55. OpenAfpPerformanceData(
  56. LPWSTR lpDeviceNames
  57. )
  58. /*++
  59. Routine Description:
  60. This routine will open the Sfmsrv FSD/FSP driver to
  61. pass performance data back. This routine also initializes the data
  62. structures used to pass data back to the registry
  63. Arguments:
  64. Pointer to object ID of each device to be opened. (Will be null for
  65. MacFile).
  66. Return Value:
  67. None.
  68. --*/
  69. {
  70. LONG status;
  71. OBJECT_ATTRIBUTES SfmObjectAttributes;
  72. //
  73. // Since SCREG is multi-threaded and will call this routine in
  74. // order to service remote performance queries, this library
  75. // must keep track of how many times it has been opened (i.e.
  76. // how many threads have accessed it). the registry routines will
  77. // limit access to the initialization routine to only one thread
  78. // at a time so synchronization (i.e. reentrancy) should not be
  79. // a problem
  80. //
  81. #if DBG
  82. OutputDebugString("sfmctr.dll: Open routine entered...\n");
  83. #endif
  84. if (!dwOpenCount) {
  85. // open Eventlog interface
  86. hEventLog = MonOpenEventLog();
  87. pCounterBlock = NULL; // initialize pointer to memory
  88. status = AfpAdminConnect(L"", &SfmRpcHandle);
  89. if (!NT_SUCCESS(status)) {
  90. REPORT_ERROR (SFMPERF_OPEN_FILE_DRIVER_ERROR, LOG_USER);
  91. // this is fatal, if we can't open the driver then there's no
  92. // point in continuing.
  93. goto OpenExitPoint;
  94. }
  95. bInitOK = TRUE; // ok to use this function
  96. }
  97. dwOpenCount++; // increment OPEN counter
  98. status = ERROR_SUCCESS; // for successful exit
  99. OpenExitPoint:
  100. return status;
  101. }
  102. DWORD
  103. CollectAfpPerformanceData(
  104. IN LPWSTR lpValueName,
  105. IN OUT LPVOID *lppData,
  106. IN OUT LPDWORD lpcbTotalBytes,
  107. IN OUT LPDWORD lpNumObjectTypes
  108. )
  109. /*++
  110. Routine Description:
  111. This routine will return the data for the SFM counters.
  112. Arguments:
  113. IN LPWSTR lpValueName
  114. pointer to a wide character string passed by registry.
  115. IN OUT LPVOID *lppData
  116. IN: pointer to the address of the buffer to receive the completed
  117. PerfDataBlock and subordinate structures. This routine will
  118. append its data to the buffer starting at the point referenced
  119. by *lppData.
  120. OUT: points to the first byte after the data structure added by this
  121. routine. This routine updated the value at lppdata after appending
  122. its data.
  123. IN OUT LPDWORD lpcbTotalBytes
  124. IN: the address of the DWORD that tells the size in bytes of the
  125. buffer referenced by the lppData argument
  126. OUT: the number of bytes added by this routine is written to the
  127. DWORD pointed to by this argument
  128. IN OUT LPDWORD NumObjectTypes
  129. IN: the address of the DWORD to receive the number of objects added
  130. by this routine
  131. OUT: the number of objects added by this routine is written to the
  132. DWORD pointed to by this argument
  133. Return Value:
  134. ERROR_MORE_DATA if buffer passed is too small to hold data
  135. any error conditions encountered are reported to the event log if
  136. event logging is enabled.
  137. ERROR_SUCCESS if success or any other error. Errors, however are
  138. also reported to the event log.
  139. --*/
  140. {
  141. // Variables for reformating the data
  142. PAFP_STATISTICS_INFO_EX pAfpStats;
  143. NTSTATUS Status;
  144. ULONG SpaceNeeded;
  145. PDWORD pdwCounter;
  146. LARGE_INTEGER UNALIGNED * pliCounter;
  147. PERF_COUNTER_BLOCK * pPerfCounterBlock;
  148. SFM_DATA_DEFINITION * pSfmDataDefinition;
  149. // variables used for error logging
  150. DWORD dwQueryType;
  151. //
  152. // before doing anything else, see if Open went OK
  153. //
  154. if (!bInitOK) {
  155. // unable to continue because open failed.
  156. *lpcbTotalBytes = (DWORD) 0;
  157. *lpNumObjectTypes = (DWORD) 0;
  158. return ERROR_SUCCESS; // yes, this is a successful exit
  159. }
  160. // see if this is a foreign (i.e. non-NT) computer data request
  161. //
  162. dwQueryType = GetQueryType (lpValueName);
  163. if (dwQueryType == QUERY_FOREIGN) {
  164. // this routine does not service requests for data from
  165. // Non-NT computers
  166. *lpcbTotalBytes = (DWORD) 0;
  167. *lpNumObjectTypes = (DWORD) 0;
  168. return ERROR_SUCCESS;
  169. }
  170. if (dwQueryType == QUERY_ITEMS){
  171. if ( !(IsNumberInUnicodeList (SfmDataDefinition.SfmObjectType.ObjectNameTitleIndex, lpValueName))) {
  172. // request received for data object not provided by this routine
  173. *lpcbTotalBytes = (DWORD) 0;
  174. *lpNumObjectTypes = (DWORD) 0;
  175. return ERROR_SUCCESS;
  176. }
  177. }
  178. pSfmDataDefinition = (SFM_DATA_DEFINITION *) *lppData;
  179. SpaceNeeded = sizeof(SFM_DATA_DEFINITION) +
  180. SIZE_OF_SFM_PERFORMANCE_DATA;
  181. if ( *lpcbTotalBytes < SpaceNeeded ) {
  182. *lpcbTotalBytes = (DWORD) 0;
  183. *lpNumObjectTypes = (DWORD) 0;
  184. return ERROR_MORE_DATA;
  185. }
  186. //
  187. // Copy the (constant, initialized) Object Type and counter definitions
  188. // to the caller's data buffer
  189. //
  190. memmove(pSfmDataDefinition,
  191. &SfmDataDefinition,
  192. sizeof(SFM_DATA_DEFINITION));
  193. //
  194. // Format and collect SFM data from IOCTL
  195. //
  196. Status = AfpAdminStatisticsGetEx( SfmRpcHandle, (LPBYTE *)&pAfpStats);
  197. if (Status != NO_ERROR)
  198. {
  199. AfpAdminDisconnect(SfmRpcHandle);
  200. SfmRpcHandle = 0;
  201. bInitOK = FALSE;
  202. *lpcbTotalBytes = (DWORD) 0;
  203. *lpNumObjectTypes = (DWORD) 0;
  204. return ERROR_SUCCESS;
  205. }
  206. //
  207. // Go to end of SfmDataDefinitionStructure to get to PerfCounterBlock
  208. //
  209. pPerfCounterBlock = (PERF_COUNTER_BLOCK *) &pSfmDataDefinition[1];
  210. pPerfCounterBlock->ByteLength = SIZE_OF_SFM_PERFORMANCE_DATA;
  211. // Go to end of PerfCounterBlock to get to array of counters
  212. pdwCounter = (PDWORD) (&pPerfCounterBlock[1]);
  213. *pdwCounter++ = pAfpStats->stat_MaxPagedUsage;
  214. *pdwCounter++ = pAfpStats->stat_CurrPagedUsage;
  215. *pdwCounter++ = pAfpStats->stat_MaxNonPagedUsage;
  216. *pdwCounter++ = pAfpStats->stat_CurrNonPagedUsage;
  217. *pdwCounter++ = pAfpStats->stat_CurrentSessions;
  218. *pdwCounter++ = pAfpStats->stat_MaxSessions;
  219. *pdwCounter++ = pAfpStats->stat_CurrentInternalOpens;
  220. *pdwCounter++ = pAfpStats->stat_MaxInternalOpens;
  221. *pdwCounter++ = pAfpStats->stat_NumFailedLogins;
  222. pliCounter = (LARGE_INTEGER UNALIGNED *) pdwCounter;
  223. pliCounter->QuadPart = pAfpStats->stat_DataRead.QuadPart +
  224. pAfpStats->stat_DataReadInternal.QuadPart;
  225. pliCounter++;
  226. pliCounter->QuadPart = pAfpStats->stat_DataWritten.QuadPart +
  227. pAfpStats->stat_DataWrittenInternal.QuadPart;
  228. pliCounter++;
  229. *pliCounter++ = pAfpStats->stat_DataIn;
  230. *pliCounter++ = pAfpStats->stat_DataOut;
  231. pdwCounter = (PDWORD) pliCounter;
  232. *pdwCounter++ = pAfpStats->stat_CurrQueueLength;
  233. *pdwCounter++ = pAfpStats->stat_MaxQueueLength;
  234. *pdwCounter++ = pAfpStats->stat_CurrThreadCount;
  235. *pdwCounter++ = pAfpStats->stat_MaxThreadCount;
  236. *lppData = (PVOID) pdwCounter;
  237. // update arguments for return
  238. *lpNumObjectTypes = 1;
  239. *lpcbTotalBytes = (DWORD)((PBYTE) pdwCounter - (PBYTE) pSfmDataDefinition);
  240. AfpAdminBufferFree(pAfpStats);
  241. return ERROR_SUCCESS;
  242. }
  243. DWORD
  244. CloseAfpPerformanceData(
  245. )
  246. /*++
  247. Routine Description:
  248. This routine closes the open handles to MacFile device performance counters
  249. Arguments:
  250. None.
  251. Return Value:
  252. ERROR_SUCCESS
  253. --*/
  254. {
  255. if (!(--dwOpenCount))
  256. {
  257. // when this is the last thread...
  258. if (SfmRpcHandle != 0)
  259. AfpAdminDisconnect(SfmRpcHandle);
  260. pCounterBlock = NULL;
  261. MonCloseEventLog();
  262. }
  263. return ERROR_SUCCESS;
  264. }
  265.