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.

287 lines
7.6 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows NT **/
  3. /** Copyright(c) Microsoft Corp., 1993 **/
  4. /**********************************************************************/
  5. /*
  6. perfw3.c
  7. This file implements the Extensible Performance Objects for
  8. the W3 Server service.
  9. FILE HISTORY:
  10. KeithMo 07-Jun-1993 Created, based on RussBl's sample code.
  11. MuraliK 16-Nov-1995 Modified dependencies and removed NetApi
  12. SophiaC 06-Nov-1996 Supported mutlitiple instances
  13. MingLu 21-Nov-1999 Optimized W3 performance counter routine
  14. */
  15. #include <windows.h>
  16. #include <winperf.h>
  17. #include <lm.h>
  18. #include <iis64.h>
  19. #include "iisinfo.h"
  20. #include "w3svc.h"
  21. #include "w3ctrs.h"
  22. #include "w3msg.h"
  23. #include "perfutil.h"
  24. #define APP_NAME (TEXT("W3Ctrs"))
  25. //
  26. // Private globals.
  27. //
  28. DWORD cOpens = 0; // Active "opens" reference count.
  29. BOOL fInitOK = FALSE; // TRUE if DLL initialized OK.
  30. DWORD cbTotalRequired = 0; // Total space for retrieving perf data
  31. HANDLE hEventLog = NULL; // Event log handle
  32. //
  33. // Public prototypes.
  34. //
  35. PM_OPEN_PROC OpenW3PerformanceData;
  36. PM_COLLECT_PROC CollectW3PerformanceData;
  37. PM_CLOSE_PROC CloseW3PerformanceData;
  38. //
  39. // Public functions.
  40. //
  41. /*******************************************************************
  42. NAME: OpenW3PerformanceData
  43. SYNOPSIS: Initializes the data structures used to communicate
  44. performance counters with the registry.
  45. ENTRY: lpDeviceNames - Poitner to object ID of each device
  46. to be opened.
  47. RETURNS: DWORD - Win32 status code.
  48. HISTORY:
  49. KeithMo 07-Jun-1993 Created.
  50. ********************************************************************/
  51. DWORD OpenW3PerformanceData( LPWSTR lpDeviceNames )
  52. {
  53. NET_API_STATUS neterr;
  54. //
  55. // Since WINLOGON is multi-threaded and will call this routine in
  56. // order to service remote performance queries, this library
  57. // must keep track of how many times it has been opened (i.e.
  58. // how many threads have accessed it). The registry routines will
  59. // limit access to the initialization routine to only one thread
  60. // at a time so synchronization (i.e. reentrancy) should not be
  61. // a problem.
  62. //
  63. if( !fInitOK )
  64. {
  65. //
  66. // This is the *first* open.
  67. //
  68. // open event log interface
  69. if (hEventLog == NULL){
  70. hEventLog = RegisterEventSource (
  71. (LPTSTR)NULL, // Use Local Machine
  72. APP_NAME // event log app name to find in registry
  73. );
  74. if (hEventLog == NULL)
  75. {
  76. return GetLastError();
  77. }
  78. }
  79. // call rpc to init remote data structure for w3 counters
  80. neterr = InitW3CounterStructure(NULL,
  81. &cbTotalRequired
  82. );
  83. // log rpc err info to event log
  84. if( neterr != NERR_Success )
  85. {
  86. // if the server is down, we don't log an error.
  87. if ( !( neterr == RPC_S_SERVER_UNAVAILABLE ||
  88. neterr == RPC_S_UNKNOWN_IF ||
  89. neterr == ERROR_SERVICE_NOT_ACTIVE ||
  90. neterr == RPC_S_CALL_FAILED_DNE ))
  91. {
  92. ReportEvent (hEventLog, EVENTLOG_ERROR_TYPE,
  93. 0, W3_UNABLE_QUERY_W3SVC_DATA,
  94. (PSID)NULL, 0,
  95. sizeof(neterr), NULL,
  96. (PVOID)(&neterr));
  97. }
  98. return ERROR_SUCCESS;
  99. }
  100. if( cbTotalRequired == 0 )
  101. {
  102. return ERROR_SUCCESS;
  103. }
  104. fInitOK = true;
  105. }
  106. //
  107. // Bump open counter.
  108. //
  109. InterlockedIncrement((LPLONG)&cOpens);
  110. return ERROR_SUCCESS;
  111. } // OpenW3PerformanceData
  112. /*******************************************************************
  113. NAME: CollectW3PerformanceData
  114. SYNOPSIS: Initializes the data structures used to communicate
  115. ENTRY: lpValueName - The name of the value to retrieve.
  116. lppData - On entry contains a pointer to the buffer to
  117. receive the completed PerfDataBlock & subordinate
  118. structures. On exit, points to the first bytes
  119. *after* the data structures added by this routine.
  120. lpcbTotalBytes - On entry contains a pointer to the
  121. size (in BYTEs) of the buffer referenced by lppData.
  122. On exit, contains the number of BYTEs added by this
  123. routine.
  124. lpNumObjectTypes - Receives the number of objects added
  125. by this routine.
  126. RETURNS: DWORD - Win32 status code. MUST be either NO_ERROR
  127. or ERROR_MORE_DATA.
  128. HISTORY:
  129. KeithMo 07-Jun-1993 Created.
  130. ********************************************************************/
  131. DWORD CollectW3PerformanceData( LPWSTR lpValueName,
  132. LPVOID * lppData,
  133. LPDWORD lpcbTotalBytes,
  134. LPDWORD lpNumObjectTypes )
  135. {
  136. NET_API_STATUS neterr;
  137. LPBYTE * lppPerfData = (LPBYTE*)lppData;
  138. //
  139. // No need to even try if we failed to open...
  140. //
  141. if( !fInitOK )
  142. {
  143. *lpcbTotalBytes = 0;
  144. *lpNumObjectTypes = 0;
  145. //
  146. // According to the Performance Counter design, this
  147. // is a successful exit. Go figure.
  148. //
  149. return ERROR_SUCCESS;
  150. }
  151. if( *lpcbTotalBytes < cbTotalRequired ){
  152. //*lpcbTotalBytes = cbTotalRequired;
  153. return ERROR_MORE_DATA;
  154. }
  155. //One rpc call to get all the counters infomation
  156. neterr = CollectW3PerfData(
  157. NULL,
  158. lpValueName,
  159. *lppPerfData,
  160. lpcbTotalBytes,
  161. lpNumObjectTypes
  162. );
  163. // log rpc err info to event log
  164. if( neterr != NERR_Success )
  165. {
  166. // if the server is down, we don't log an error.
  167. if ( !( neterr == RPC_S_SERVER_UNAVAILABLE ||
  168. neterr == RPC_S_UNKNOWN_IF ||
  169. neterr == ERROR_SERVICE_NOT_ACTIVE ||
  170. neterr == RPC_S_CALL_FAILED_DNE ))
  171. {
  172. ReportEvent (hEventLog, EVENTLOG_ERROR_TYPE,
  173. 0, W3_UNABLE_QUERY_W3SVC_DATA,
  174. (PSID)NULL, 0,
  175. sizeof(neterr), NULL,
  176. (PVOID)(&neterr));
  177. }
  178. *lpcbTotalBytes = 0;
  179. *lpNumObjectTypes = 0;
  180. return ERROR_SUCCESS;
  181. }
  182. // align the total bytes to a QWORD_MULTIPLE
  183. *lpcbTotalBytes = QWORD_MULTIPLE(*lpcbTotalBytes);
  184. if( *lpcbTotalBytes && *lpNumObjectTypes )
  185. {
  186. *lppData = *lppPerfData + *lpcbTotalBytes;
  187. }
  188. return ERROR_SUCCESS;
  189. } // CollectW3PerformanceData
  190. /*******************************************************************
  191. NAME: CloseW3PerformanceData
  192. SYNOPSIS: Terminates the performance counters.
  193. RETURNS: DWORD - Win32 status code.
  194. HISTORY:
  195. KeithMo 07-Jun-1993 Created.
  196. ********************************************************************/
  197. DWORD CloseW3PerformanceData( VOID )
  198. {
  199. //
  200. // No real cleanup to do here.
  201. //
  202. DWORD dwCount = InterlockedDecrement((LPLONG)&cOpens);
  203. if (dwCount == 0)
  204. {
  205. if (hEventLog != NULL)
  206. {
  207. DeregisterEventSource (hEventLog);
  208. hEventLog = NULL;
  209. }
  210. }
  211. return ERROR_SUCCESS;
  212. } // CloseW3PerformanceData