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.

556 lines
17 KiB

  1. /*++ BUILD Version: 0001 // Increment this if a change has global effects
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. perfatk.c
  5. Abstract:
  6. This file implements the Extensible Objects for
  7. the Appletalk object types
  8. Created:
  9. 10/11/93 Sue Adams (suea)
  10. Revision History
  11. 02/23/94 Sue Adams - No longer need to open registry key
  12. \AppleTalk\Performance to query FirstCounter and
  13. FirstHelp indices. These are now hardcoded as
  14. part of the base NT system.
  15. ATKOBJ = 1050, ATKOBJ_HELP = 1051,
  16. PKTDROPPED = 1096, PKTDROPPED_HELP = 1097
  17. --*/
  18. //
  19. // Include Files
  20. //
  21. #include <nt.h>
  22. #include <ntrtl.h>
  23. #include <nturtl.h>
  24. #include <ntprfctr.h>
  25. #include <windows.h>
  26. #include <string.h>
  27. #include <wcstr.h>
  28. #include <winperf.h>
  29. #define GLOBAL extern
  30. #define EQU ; /##/
  31. #define ATALK_SPIN_LOCK LONG
  32. #define PMDL PVOID
  33. #include <atkstat.h>
  34. #include <tdi.h>
  35. #include <atalktdi.h>
  36. #include "atkctrs.h" // error message definition
  37. #include "perfmsg.h"
  38. #include "perfutil.h"
  39. #include "dataatk.h"
  40. #include <atkstat.h>
  41. //
  42. // References to constants which initialize the Object type definitions
  43. // (see dataatk.h & .c)
  44. //
  45. #define MAX_PORTS 32
  46. extern ATK_DATA_DEFINITION AtkDataDefinition;
  47. DWORD dwOpenCount = 0; // count of "Open" threads
  48. BOOL bInitOK = FALSE; // true = DLL initialized OK
  49. HANDLE AddressHandle = NULL; // handle to appletalk driver
  50. DWORD LengthOfInstanceNames = 0; // including padding to DWORD length
  51. int NumOfDevices = 0; // Number of appletalk ports with stats
  52. PATALK_STATS pAtalkStats;
  53. PATALK_PORT_STATS pAtalkPortStats;
  54. CHAR Buffer[ sizeof(ATALK_STATS) +
  55. sizeof(ATALK_PORT_STATS) * MAX_PORTS +
  56. sizeof(GET_STATISTICS_ACTION)];
  57. PGET_STATISTICS_ACTION GetStats = (PGET_STATISTICS_ACTION)Buffer;
  58. //
  59. // Function Prototypes
  60. //
  61. PM_OPEN_PROC OpenAtkPerformanceData;
  62. PM_COLLECT_PROC CollectAtkPerformanceData;
  63. PM_CLOSE_PROC CloseAtkPerformanceData;
  64. DWORD
  65. OpenAtkPerformanceData(
  66. LPWSTR lpDeviceNames
  67. )
  68. /*++
  69. Routine Description:
  70. This routine will open the Appletalk driver and remember the handle
  71. returned to be used in subsequent Ioctls for performance data to the
  72. driver. Each device name exported by Appletalk will be mapped to an
  73. array index into the performance data arrays for all the ports handled
  74. by Appletalk. These indices will then be used in the collect routine
  75. to know which set of performance data belongs to which device.
  76. Arguments:
  77. Pointer to each device to be opened. Note that for Appletalk, we do not
  78. actually open each device (port), we only open one Tdi provider name to
  79. use when ioctling the driver for performance data on all ports.
  80. Return Value:
  81. None.
  82. --*/
  83. {
  84. NTSTATUS Status = ERROR_SUCCESS;
  85. UNICODE_STRING DriverName;
  86. IO_STATUS_BLOCK IoStatusBlock;
  87. OBJECT_ATTRIBUTES ObjectAttributes;
  88. LPWSTR lpLocalDeviceNames;
  89. int i;
  90. if (!dwOpenCount)
  91. {
  92. if ((lpLocalDeviceNames = lpDeviceNames) == NULL)
  93. return ERROR_INVALID_NAME; // There are no devices to query
  94. MonOpenEventLog();
  95. // Open the Appletalk driver and obtain the device (port)/index
  96. // mappings for performance data table
  97. RtlInitUnicodeString(&DriverName, ATALKPAP_DEVICENAME);
  98. InitializeObjectAttributes (
  99. &ObjectAttributes,
  100. &DriverName,
  101. 0,
  102. NULL,
  103. NULL);
  104. Status = NtCreateFile(
  105. &AddressHandle,
  106. GENERIC_READ | SYNCHRONIZE, // desired access.
  107. &ObjectAttributes, // object attributes.
  108. &IoStatusBlock, // returned status information.
  109. 0, // block size (unused).
  110. 0, // file attributes.
  111. FILE_SHARE_READ, // share access.
  112. FILE_OPEN, // create disposition.
  113. FILE_SYNCHRONOUS_IO_NONALERT, // create options.
  114. NULL,
  115. 0);
  116. if (!NT_SUCCESS(Status))
  117. {
  118. REPORT_ERROR_DATA (ATK_OPEN_FILE_ERROR, LOG_USER,
  119. &IoStatusBlock, sizeof(IoStatusBlock));
  120. return RtlNtStatusToDosError(Status);
  121. }
  122. //
  123. // Now make a NtDeviceIoControl file (corresponding to TdiAction) to
  124. // get the statistics - here we are only interested in the array
  125. // of device/port names
  126. //
  127. GetStats->ActionHeader.ActionCode = COMMON_ACTION_GETSTATISTICS;
  128. GetStats->ActionHeader.TransportId = MATK;
  129. Status = NtDeviceIoControlFile(
  130. AddressHandle,
  131. NULL,
  132. NULL,
  133. NULL,
  134. &IoStatusBlock,
  135. IOCTL_TDI_ACTION,
  136. NULL,
  137. 0,
  138. (PVOID)GetStats,
  139. sizeof(Buffer));
  140. if (!NT_SUCCESS(Status))
  141. {
  142. REPORT_ERROR_DATA (ATK_IOCTL_FILE_ERROR, LOG_DEBUG,
  143. &IoStatusBlock, sizeof(IoStatusBlock));
  144. NtClose(AddressHandle);
  145. return RtlNtStatusToDosError(Status);
  146. }
  147. pAtalkStats = (PATALK_STATS)(Buffer + sizeof(GET_STATISTICS_ACTION));
  148. pAtalkPortStats = (PATALK_PORT_STATS)( Buffer +
  149. sizeof(GET_STATISTICS_ACTION) +
  150. sizeof(ATALK_STATS));
  151. NumOfDevices = pAtalkStats->stat_NumActivePorts;
  152. for (i = 0; i < NumOfDevices; i++, pAtalkPortStats ++)
  153. {
  154. LengthOfInstanceNames +=
  155. DWORD_MULTIPLE((lstrlenW(pAtalkPortStats->prtst_PortName) * sizeof(WCHAR)));
  156. }
  157. bInitOK = TRUE; // ok to use this function
  158. } // end if dwOpenCount is zero (first opener)
  159. if (!NT_SUCCESS(Status))
  160. {
  161. if (AddressHandle != NULL)
  162. {
  163. NtClose(AddressHandle);
  164. }
  165. return RtlNtStatusToDosError(Status);
  166. }
  167. else
  168. {
  169. dwOpenCount++; // increment OPEN counter
  170. REPORT_INFORMATION (ATK_OPEN_PERFORMANCE_DATA, LOG_DEBUG);
  171. }
  172. return Status;
  173. }
  174. DWORD
  175. CollectAtkPerformanceData(
  176. IN LPWSTR lpValueName,
  177. IN OUT LPVOID *lppData,
  178. IN OUT LPDWORD lpcbTotalBytes,
  179. IN OUT LPDWORD lpNumObjectTypes
  180. )
  181. /*++
  182. Routine Description:
  183. This routine will return the data for the AppleTalk counters.
  184. Arguments:
  185. IN LPWSTR lpValueName
  186. pointer to a wide character string passed by registry.
  187. IN OUT LPVOID *lppData
  188. IN: pointer to the address of the buffer to receive the completed
  189. PerfDataBlock and subordinate structures. This routine will
  190. append its data to the buffer starting at the point referenced
  191. by *lppData.
  192. OUT: points to the first byte after the data structure added by this
  193. routine. This routine updates the value at lppdata after appending
  194. its data.
  195. IN OUT LPDWORD lpcbTotalBytes
  196. IN: the address of the DWORD that tells the size in bytes of the
  197. buffer referenced by the lppData argument
  198. OUT: the number of bytes added by this routine is writted to the
  199. DWORD pointed to by this argument
  200. IN OUT LPDWORD NumObjectTypes
  201. IN: the address of the DWORD to receive the number of objects added
  202. by this routine
  203. OUT: the number of objects added by this routine is writted to the
  204. DWORD pointed to by this argument
  205. Return Value:
  206. ERROR_MORE_DATA if buffer passed is too small to hold data
  207. any error conditions encountered are reported to the event log if
  208. event logging is enabled.
  209. ERROR_SUCCESS if success or any other error. Errors, however are
  210. also reported to the event log.
  211. --*/
  212. {
  213. // Variables for reformating the data
  214. ULONG SpaceNeeded;
  215. PDWORD pdwCounter;
  216. LARGE_INTEGER UNALIGNED *pliCounter;
  217. LARGE_INTEGER li1000;
  218. PERF_COUNTER_BLOCK *pPerfCounterBlock;
  219. ATK_DATA_DEFINITION *pAtkDataDefinition;
  220. PERF_INSTANCE_DEFINITION *pPerfInstanceDefinition;
  221. int i;
  222. UNICODE_STRING UCurDeviceName;
  223. // Variables for collecting the data from Appletalk
  224. NTSTATUS Status;
  225. IO_STATUS_BLOCK IoStatusBlock;
  226. DWORD dwQueryType;
  227. li1000.QuadPart = 1000;
  228. //
  229. // before doing anything else, see if Open went OK
  230. //
  231. if (!bInitOK) {
  232. // unable to continue because open failed.
  233. *lpcbTotalBytes = (DWORD) 0;
  234. *lpNumObjectTypes = (DWORD) 0;
  235. return ERROR_SUCCESS; // yes, this is a successful exit
  236. }
  237. if (lpValueName == NULL) {
  238. REPORT_INFORMATION (ATK_COLLECT_ENTERED, LOG_VERBOSE);
  239. } else {
  240. REPORT_INFORMATION_DATA (ATK_COLLECT_ENTERED,
  241. LOG_VERBOSE,
  242. lpValueName,
  243. (DWORD)(lstrlenW(lpValueName)*sizeof(WCHAR)));
  244. }
  245. //
  246. // see if this is a foreign (i.e. non-NT) computer data request
  247. //
  248. dwQueryType = GetQueryType (lpValueName);
  249. if ((dwQueryType == QUERY_COSTLY) || (dwQueryType == QUERY_FOREIGN)) {
  250. // ATK foreign data requests are not supported so bail out
  251. REPORT_INFORMATION (ATK_FOREIGN_DATA_REQUEST, LOG_VERBOSE);
  252. *lpcbTotalBytes = (DWORD) 0;
  253. *lpNumObjectTypes = (DWORD) 0;
  254. return ERROR_SUCCESS;
  255. }
  256. if (dwQueryType == QUERY_ITEMS){
  257. if ( !(IsNumberInUnicodeList (AtkDataDefinition.AtkObjectType.ObjectNameTitleIndex,
  258. lpValueName)))
  259. {
  260. // request received for data object not provided by this routine
  261. REPORT_INFORMATION (ATK_UNSUPPORTED_ITEM_REQUEST, LOG_VERBOSE);
  262. *lpcbTotalBytes = (DWORD) 0;
  263. *lpNumObjectTypes = (DWORD) 0;
  264. return ERROR_SUCCESS;
  265. }
  266. }
  267. pAtkDataDefinition = (ATK_DATA_DEFINITION *) *lppData;
  268. // Compute space needed to hold AppleTalk performance Data
  269. SpaceNeeded = sizeof(ATK_DATA_DEFINITION) +
  270. (NumOfDevices *
  271. (SIZE_ATK_PERFORMANCE_DATA +
  272. sizeof(PERF_INSTANCE_DEFINITION))) +
  273. LengthOfInstanceNames;
  274. if ( *lpcbTotalBytes < SpaceNeeded ) {
  275. *lpcbTotalBytes = (DWORD) SpaceNeeded;
  276. *lpNumObjectTypes = (DWORD) 0;
  277. return ERROR_MORE_DATA;
  278. }
  279. //
  280. // Copy the (constant, initialized) Object Type and counter definitions
  281. //
  282. RtlMoveMemory(pAtkDataDefinition,
  283. &AtkDataDefinition,
  284. sizeof(ATK_DATA_DEFINITION));
  285. //
  286. // Format and collect SFM data from IOCTL
  287. //
  288. GetStats->ActionHeader.ActionCode = COMMON_ACTION_GETSTATISTICS;
  289. GetStats->ActionHeader.TransportId = MATK;
  290. Status = NtDeviceIoControlFile(
  291. AddressHandle,
  292. NULL,
  293. NULL,
  294. NULL,
  295. &IoStatusBlock,
  296. IOCTL_TDI_ACTION,
  297. NULL,
  298. 0,
  299. (PVOID)GetStats,
  300. sizeof(Buffer));
  301. if ((!NT_SUCCESS(Status)) || (!NT_SUCCESS(IoStatusBlock.Status)))
  302. {
  303. REPORT_ERROR_DATA (ATK_IOCTL_FILE_ERROR, LOG_DEBUG,
  304. &IoStatusBlock, sizeof(IoStatusBlock));
  305. *lpcbTotalBytes = (DWORD) 0;
  306. *lpNumObjectTypes = (DWORD) 0;
  307. return ERROR_SUCCESS;
  308. }
  309. // The real statistics data starts after the TDI action header
  310. pAtalkStats = (ATALK_STATS *)(Buffer + sizeof(GET_STATISTICS_ACTION));
  311. pAtalkPortStats = (PATALK_PORT_STATS)( Buffer +
  312. sizeof(GET_STATISTICS_ACTION) +
  313. sizeof(ATALK_STATS));
  314. //
  315. // due to some PnP event, if one more adapter has come in, make adjustments!
  316. //
  317. if (pAtalkStats->stat_NumActivePorts > (DWORD)NumOfDevices)
  318. {
  319. NumOfDevices = pAtalkStats->stat_NumActivePorts;
  320. LengthOfInstanceNames = 0;
  321. for (i = 0; i < NumOfDevices; i++, pAtalkPortStats ++)
  322. {
  323. LengthOfInstanceNames +=
  324. DWORD_MULTIPLE((lstrlenW(pAtalkPortStats->prtst_PortName) * sizeof(WCHAR)));
  325. }
  326. SpaceNeeded = sizeof(ATK_DATA_DEFINITION) +
  327. (NumOfDevices * (SIZE_ATK_PERFORMANCE_DATA +
  328. sizeof(PERF_INSTANCE_DEFINITION))) +
  329. LengthOfInstanceNames;
  330. if ( *lpcbTotalBytes < SpaceNeeded ) {
  331. *lpcbTotalBytes = (DWORD) SpaceNeeded;
  332. *lpNumObjectTypes = (DWORD) 0;
  333. return ERROR_MORE_DATA;
  334. }
  335. }
  336. // Now point to the location where the first instance definition will go
  337. pPerfInstanceDefinition = (PERF_INSTANCE_DEFINITION *)&pAtkDataDefinition[1];
  338. for (i = 0; i < NumOfDevices; i++, pAtalkPortStats ++)
  339. {
  340. //
  341. // Format Appletalk statistics for each active port (instance)
  342. //
  343. RtlInitUnicodeString(&UCurDeviceName, pAtalkPortStats->prtst_PortName);
  344. MonBuildInstanceDefinition(
  345. pPerfInstanceDefinition,
  346. (PVOID *)&pPerfCounterBlock,
  347. 0,
  348. 0,
  349. i,
  350. &UCurDeviceName);
  351. pPerfCounterBlock->ByteLength = SIZE_ATK_PERFORMANCE_DATA;
  352. pdwCounter = (PDWORD) (&pPerfCounterBlock[1]);
  353. // Begin filling in the actual counter data
  354. *pdwCounter++ = pAtalkPortStats->prtst_NumPacketsIn;
  355. *pdwCounter++ = pAtalkPortStats->prtst_NumPacketsOut;
  356. pliCounter = (LARGE_INTEGER UNALIGNED *) pdwCounter;
  357. *pliCounter++ = pAtalkPortStats->prtst_DataIn;
  358. *pliCounter++ = pAtalkPortStats->prtst_DataOut;
  359. *pliCounter = pAtalkPortStats->prtst_DdpPacketInProcessTime;
  360. // convert this to 1msec time base
  361. pliCounter->QuadPart = li1000.QuadPart * (pliCounter->QuadPart/pAtalkStats->stat_PerfFreq.QuadPart);
  362. pdwCounter = (PDWORD) ++pliCounter;
  363. *pdwCounter++ = pAtalkPortStats->prtst_NumDdpPacketsIn;
  364. pliCounter = (LARGE_INTEGER UNALIGNED *) pdwCounter;
  365. *pliCounter = pAtalkPortStats->prtst_AarpPacketInProcessTime;
  366. // convert this to 1msec time base
  367. pliCounter->QuadPart = li1000.QuadPart * (pliCounter->QuadPart/pAtalkStats->stat_PerfFreq.QuadPart);
  368. pdwCounter = (PDWORD) ++pliCounter;
  369. *pdwCounter++ = pAtalkPortStats->prtst_NumAarpPacketsIn;
  370. pliCounter = (LARGE_INTEGER UNALIGNED *) pdwCounter;
  371. *pliCounter = pAtalkStats->stat_AtpPacketInProcessTime;
  372. // convert this to 1msec time base
  373. pliCounter->QuadPart = li1000.QuadPart * (pliCounter->QuadPart, pAtalkStats->stat_PerfFreq.QuadPart);
  374. pdwCounter = (PDWORD) ++pliCounter;
  375. *pdwCounter++ = pAtalkStats->stat_AtpNumPackets;
  376. *pdwCounter++ = pAtalkStats->stat_AtpNumRespTimeout;
  377. *pdwCounter++ = pAtalkStats->stat_AtpNumLocalRetries;
  378. *pdwCounter++ = pAtalkStats->stat_AtpNumRemoteRetries;
  379. *pdwCounter++ = pAtalkStats->stat_AtpNumXoResponse;
  380. *pdwCounter++ = pAtalkStats->stat_AtpNumAloResponse;
  381. *pdwCounter++ = pAtalkStats->stat_AtpNumRecdRelease;
  382. pliCounter = (LARGE_INTEGER UNALIGNED *) pdwCounter;
  383. *pliCounter = pAtalkPortStats->prtst_NbpPacketInProcessTime;
  384. // convert this to 1msec time base
  385. pliCounter->QuadPart = li1000.QuadPart * (pliCounter->QuadPart, pAtalkStats->stat_PerfFreq.QuadPart);
  386. pdwCounter = (PDWORD) ++pliCounter;
  387. *pdwCounter++ = pAtalkPortStats->prtst_NumNbpPacketsIn;
  388. pliCounter = (LARGE_INTEGER UNALIGNED *) pdwCounter;
  389. *pliCounter = pAtalkPortStats->prtst_ZipPacketInProcessTime;
  390. // convert this to 1msec time base
  391. pliCounter->QuadPart = li1000.QuadPart * (pliCounter->QuadPart, pAtalkStats->stat_PerfFreq.QuadPart);
  392. pdwCounter = (PDWORD) ++pliCounter;
  393. *pdwCounter++ = pAtalkPortStats->prtst_NumZipPacketsIn;
  394. pliCounter = (LARGE_INTEGER UNALIGNED *) pdwCounter;
  395. *pliCounter = pAtalkPortStats->prtst_RtmpPacketInProcessTime;
  396. // convert this to 1msec time base
  397. pliCounter->QuadPart = li1000.QuadPart * (pliCounter->QuadPart, pAtalkStats->stat_PerfFreq.QuadPart);
  398. pdwCounter = (PDWORD) ++pliCounter;
  399. *pdwCounter++ = pAtalkPortStats->prtst_NumRtmpPacketsIn;
  400. *pdwCounter++ = pAtalkStats->stat_CurAllocSize;
  401. *pdwCounter++ = pAtalkPortStats->prtst_NumPktRoutedIn;
  402. *pdwCounter++ = pAtalkPortStats->prtst_NumPktRoutedOut;
  403. *pdwCounter++ = pAtalkPortStats->prtst_NumPktDropped;
  404. pdwCounter++; // 8-byte-alignment pad
  405. pPerfInstanceDefinition = (PERF_INSTANCE_DEFINITION *)
  406. ((PBYTE) pPerfCounterBlock +
  407. SIZE_ATK_PERFORMANCE_DATA);
  408. }
  409. pAtkDataDefinition->AtkObjectType.NumInstances = NumOfDevices;
  410. pAtkDataDefinition->AtkObjectType.TotalByteLength =
  411. (DWORD)((PBYTE) pdwCounter - (PBYTE) pAtkDataDefinition);
  412. *lppData = pdwCounter;
  413. *lpcbTotalBytes = (DWORD)((PBYTE) pdwCounter - (PBYTE) pAtkDataDefinition);
  414. *lpNumObjectTypes = 1;
  415. REPORT_INFORMATION (ATK_COLLECT_DATA, LOG_DEBUG);
  416. return ERROR_SUCCESS;
  417. }
  418. DWORD
  419. CloseAtkPerformanceData(
  420. )
  421. /*++
  422. Routine Description:
  423. This routine closes the open handles to Appletalk driver and eventlog.
  424. Arguments:
  425. None.
  426. Return Value:
  427. ERROR_SUCCESS
  428. --*/
  429. {
  430. REPORT_INFORMATION (ATK_CLOSE_ENTERED, LOG_VERBOSE);
  431. if (!(--dwOpenCount)) { // when this is the last thread...
  432. NtClose(AddressHandle);
  433. MonCloseEventLog();
  434. }
  435. return ERROR_SUCCESS;
  436. }
  437.