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.

409 lines
9.9 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. perfnet.c
  5. Abstract:
  6. Author:
  7. Bob Watson (a-robw) Aug 95
  8. Revision History:
  9. --*/
  10. #include <nt.h>
  11. #include <ntrtl.h>
  12. #include <nturtl.h>
  13. #include <windows.h>
  14. #include <winperf.h>
  15. #include <ntprfctr.h>
  16. #include <assert.h>
  17. #include <perfutil.h>
  18. #include "perfnet.h"
  19. #include "netsvcmc.h"
  20. // bit field definitions for collect function flags
  21. #define POS_COLLECT_SERVER_DATA ((DWORD)0x00000001)
  22. #define POS_COLLECT_SERVER_QUEUE_DATA ((DWORD)0x00000002)
  23. #define POS_COLLECT_REDIR_DATA ((DWORD)0x00000004)
  24. #define POS_COLLECT_BROWSER_DATA ((DWORD)0x00000008)
  25. #define POS_COLLECT_GLOBAL_DATA ((DWORD)0x0000000F)
  26. #define POS_COLLECT_FOREIGN_DATA ((DWORD)0)
  27. #define POS_COLLECT_COSTLY_DATA ((DWORD)0)
  28. // global variables to this DLL
  29. HANDLE ThisDLLHandle = NULL;
  30. HANDLE hEventLog = NULL;
  31. HANDLE hLibHeap = NULL;
  32. // variables local to this module
  33. static POS_FUNCTION_INFO posDataFuncInfo[] = {
  34. {SERVER_OBJECT_TITLE_INDEX, POS_COLLECT_SERVER_DATA, 0, CollectServerObjectData},
  35. {SERVER_QUEUE_OBJECT_TITLE_INDEX, POS_COLLECT_SERVER_QUEUE_DATA, 0, CollectServerQueueObjectData},
  36. {REDIRECTOR_OBJECT_TITLE_INDEX, POS_COLLECT_REDIR_DATA, 0, CollectRedirObjectData},
  37. {BROWSER_OBJECT_TITLE_INDEX, POS_COLLECT_BROWSER_DATA, 0, CollectBrowserObjectData}
  38. };
  39. #define POS_NUM_FUNCS (sizeof(posDataFuncInfo) / sizeof(posDataFuncInfo[1]))
  40. static bInitOk = FALSE;
  41. static DWORD dwOpenCount = 0;
  42. static BOOL bReportedNotOpen = FALSE;
  43. PM_OPEN_PROC OpenNetSvcsObject;
  44. PM_COLLECT_PROC CollecNetSvcsObjectData;
  45. PM_CLOSE_PROC CloseNetSvcsObject;
  46. static
  47. BOOL
  48. DllProcessAttach (
  49. IN HANDLE DllHandle
  50. )
  51. /*++
  52. Description:
  53. perform any initialization function that apply to all object
  54. modules
  55. --*/
  56. {
  57. BOOL bReturn = TRUE;
  58. UNREFERENCED_PARAMETER (DllHandle);
  59. // create heap for this library
  60. if (hLibHeap == NULL) hLibHeap = HeapCreate (0, 1, 0);
  61. assert (hLibHeap != NULL);
  62. if (hLibHeap == NULL) {
  63. return FALSE;
  64. }
  65. // open handle to the event log
  66. if (hEventLog == NULL) hEventLog = MonOpenEventLog((LPWSTR)L"PerfNet");
  67. assert (hEventLog != NULL);
  68. return bReturn;
  69. }
  70. static
  71. BOOL
  72. DllProcessDetach (
  73. IN HANDLE DllHandle
  74. )
  75. {
  76. UNREFERENCED_PARAMETER (DllHandle);
  77. if (dwOpenCount != 0) {
  78. // make sure the object has been closed before the
  79. // library is deleted.
  80. // setting dwOpenCount to 1 insures that all
  81. // the objects will be closed on this call
  82. if (dwOpenCount > 1) dwOpenCount = 1;
  83. CloseNetSvcsObject();
  84. dwOpenCount = 0;
  85. }
  86. if (hLibHeap != NULL) {
  87. HeapDestroy (hLibHeap);
  88. hLibHeap = NULL;
  89. }
  90. if (hEventLog != NULL) {
  91. MonCloseEventLog ();
  92. hEventLog = NULL;
  93. }
  94. return TRUE;
  95. }
  96. BOOL
  97. __stdcall
  98. DllInit(
  99. IN HANDLE DLLHandle,
  100. IN DWORD Reason,
  101. IN LPVOID ReservedAndUnused
  102. )
  103. {
  104. ReservedAndUnused;
  105. // this will prevent the DLL from getting
  106. // the DLL_THREAD_* messages
  107. DisableThreadLibraryCalls (DLLHandle);
  108. switch(Reason) {
  109. case DLL_PROCESS_ATTACH:
  110. return DllProcessAttach (DLLHandle);
  111. case DLL_PROCESS_DETACH:
  112. return DllProcessDetach (DLLHandle);
  113. case DLL_THREAD_ATTACH:
  114. case DLL_THREAD_DETACH:
  115. default:
  116. return TRUE;
  117. }
  118. }
  119. DWORD APIENTRY
  120. OpenNetSvcsObject (
  121. LPWSTR lpDeviceNames
  122. )
  123. /*++
  124. Routine Description:
  125. This routine will initialize the data structures used to pass
  126. data back to the registry
  127. Arguments:
  128. Pointer to object ID of each device to be opened (PerfGen)
  129. Return Value:
  130. None.
  131. --*/
  132. {
  133. DWORD status = ERROR_SUCCESS;
  134. DWORD dwErrorCount = 0;
  135. if (dwOpenCount == 0) {
  136. status = OpenServerObject (lpDeviceNames);
  137. // if this didn't open, it's not fatal, just no
  138. // server stats will be returned
  139. if (status != ERROR_SUCCESS) {
  140. dwErrorCount++;
  141. status = ERROR_SUCCESS;
  142. }
  143. status = OpenServerQueueObject (lpDeviceNames);
  144. // if this didn't open, it's not fatal, just no
  145. // server queue stats will be returned
  146. if (status != ERROR_SUCCESS) {
  147. dwErrorCount++;
  148. status = ERROR_SUCCESS;
  149. }
  150. status = OpenRedirObject (lpDeviceNames);
  151. // if this didn't open, it's not fatal, just no
  152. // Redir stats will be returned
  153. if (status != ERROR_SUCCESS) {
  154. dwErrorCount++;
  155. status = ERROR_SUCCESS;
  156. }
  157. status = OpenBrowserObject (lpDeviceNames);
  158. // if this didn't open, it's not fatal, just no
  159. // Browser stats will be returned
  160. if (status != ERROR_SUCCESS) {
  161. dwErrorCount++;
  162. status = ERROR_SUCCESS;
  163. }
  164. if (dwErrorCount < POS_NUM_FUNCS) {
  165. // then at least one object opened OK so continue
  166. bInitOk = TRUE;
  167. dwOpenCount++;
  168. } else {
  169. // none of the objects opened, so give up.
  170. ReportEvent (hEventLog,
  171. EVENTLOG_ERROR_TYPE,
  172. 0,
  173. PERFNET_UNABLE_OPEN,
  174. NULL,
  175. 0,
  176. sizeof(DWORD),
  177. NULL,
  178. (LPVOID)&status);
  179. }
  180. } else {
  181. // already opened so bump the refcount
  182. dwOpenCount++;
  183. }
  184. return status;
  185. }
  186. DWORD APIENTRY
  187. CollectNetSvcsObjectData (
  188. IN LPWSTR lpValueName,
  189. IN OUT LPVOID *lppData,
  190. IN OUT LPDWORD lpcbTotalBytes,
  191. IN OUT LPDWORD lpNumObjectTypes
  192. )
  193. /*++
  194. Routine Description:
  195. This routine will return the data for the processor object
  196. Arguments:
  197. IN OUT LPVOID *lppData
  198. IN: pointer to the address of the buffer to receive the completed
  199. PerfDataBlock and subordinate structures. This routine will
  200. append its data to the buffer starting at the point referenced
  201. by *lppData.
  202. OUT: points to the first byte after the data structure added by this
  203. routine. This routine updated the value at lppdata after appending
  204. its data.
  205. IN OUT LPDWORD lpcbTotalBytes
  206. IN: the address of the DWORD that tells the size in bytes of the
  207. buffer referenced by the lppData argument
  208. OUT: the number of bytes added by this routine is writted to the
  209. DWORD pointed to by this argument
  210. IN OUT LPDWORD NumObjectTypes
  211. IN: the address of the DWORD to receive the number of objects added
  212. by this routine
  213. OUT: the number of objects added by this routine is writted to the
  214. DWORD pointed to by this argument
  215. Returns:
  216. 0 if successful, else Win 32 error code of failure
  217. --*/
  218. {
  219. LONG lReturn = ERROR_SUCCESS;
  220. // build bit mask of functions to call
  221. DWORD dwQueryType;
  222. DWORD FunctionCallMask = 0;
  223. DWORD FunctionIndex;
  224. DWORD dwNumObjectsFromFunction;
  225. DWORD dwOrigBuffSize;
  226. DWORD dwByteSize;
  227. if (!bInitOk) {
  228. if (!bReportedNotOpen) {
  229. bReportedNotOpen = ReportEvent (hEventLog,
  230. EVENTLOG_ERROR_TYPE,
  231. 0,
  232. PERFNET_NOT_OPEN,
  233. NULL,
  234. 0,
  235. 0,
  236. NULL,
  237. NULL);
  238. }
  239. *lpcbTotalBytes = (DWORD) 0;
  240. *lpNumObjectTypes = (DWORD) 0;
  241. lReturn = ERROR_SUCCESS;
  242. goto COLLECT_BAIL_OUT;
  243. }
  244. dwQueryType = GetQueryType (lpValueName);
  245. switch (dwQueryType) {
  246. case QUERY_ITEMS:
  247. for (FunctionIndex = 0; FunctionIndex < POS_NUM_FUNCS; FunctionIndex++) {
  248. if (IsNumberInUnicodeList (
  249. posDataFuncInfo[FunctionIndex].dwObjectId, lpValueName)) {
  250. FunctionCallMask |=
  251. posDataFuncInfo[FunctionIndex].dwCollectFunctionBit;
  252. }
  253. }
  254. break;
  255. case QUERY_GLOBAL:
  256. FunctionCallMask = POS_COLLECT_GLOBAL_DATA;
  257. break;
  258. case QUERY_FOREIGN:
  259. FunctionCallMask = POS_COLLECT_FOREIGN_DATA;
  260. break;
  261. case QUERY_COSTLY:
  262. FunctionCallMask = POS_COLLECT_COSTLY_DATA;
  263. break;
  264. default:
  265. FunctionCallMask = POS_COLLECT_COSTLY_DATA;
  266. break;
  267. }
  268. // collect data
  269. *lpNumObjectTypes = 0;
  270. dwOrigBuffSize = dwByteSize = *lpcbTotalBytes;
  271. *lpcbTotalBytes = 0;
  272. for (FunctionIndex = 0; FunctionIndex < POS_NUM_FUNCS; FunctionIndex++) {
  273. if (posDataFuncInfo[FunctionIndex].dwCollectFunctionBit &
  274. FunctionCallMask) {
  275. dwNumObjectsFromFunction = 0;
  276. lReturn = (*posDataFuncInfo[FunctionIndex].pCollectFunction) (
  277. lppData,
  278. &dwByteSize,
  279. &dwNumObjectsFromFunction);
  280. if (lReturn == ERROR_SUCCESS) {
  281. *lpNumObjectTypes += dwNumObjectsFromFunction;
  282. *lpcbTotalBytes += dwByteSize;
  283. dwOrigBuffSize -= dwByteSize;
  284. dwByteSize = dwOrigBuffSize;
  285. } else {
  286. break;
  287. }
  288. }
  289. }
  290. // *lppData is updated by each function
  291. // *lpcbTotalBytes is updated after each successful function
  292. // *lpNumObjects is updated after each successful function
  293. COLLECT_BAIL_OUT:
  294. return lReturn;
  295. }
  296. DWORD APIENTRY
  297. CloseNetSvcsObject (
  298. )
  299. /*++
  300. Routine Description:
  301. This routine closes the open objects for the net services counters.
  302. Arguments:
  303. None.
  304. Return Value:
  305. ERROR_SUCCESS
  306. --*/
  307. {
  308. if (dwOpenCount > 0) {
  309. dwOpenCount--;
  310. }
  311. if (dwOpenCount == 0) {
  312. // close stuff here
  313. CloseServerQueueObject();
  314. CloseServerObject();
  315. CloseRedirObject();
  316. CloseBrowserObject();
  317. }
  318. return ERROR_SUCCESS;
  319. }