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.

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