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.

2009 lines
70 KiB

  1. /*++ BUILD Version: 0001 // Increment this if a change has global effects
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. perftcp.c
  5. Abstract:
  6. This file implements the Extensible Objects for
  7. the TCP/IP LAN object types
  8. Created:
  9. Christos Tsollis 08/26/92
  10. Revision History:
  11. 10/28/92 a-robw (Bob Watson)
  12. added Message Logging and Foreign Computer Support interface.
  13. --*/
  14. //
  15. // Disable SNMP interface
  16. //
  17. // This file has been modified to circumvent the SNMP service and
  18. // go right to the agent DLL. In doing this, performance has been
  19. // improved at the expense of only being able to query the local
  20. // machine. The USE_SNMP flag has been used to save as much of the
  21. // old code as possible (it used to work) but the emphesis of this
  22. // modification is to make it work "around" SNMP and, as such, the
  23. // USE_SNMP blocks of code HAVE NOT (at this time) BEEN TESTED!
  24. // Caveat Emptor! (a-robw)
  25. //
  26. #ifdef USE_SNMP
  27. #undef USE_SNMP
  28. #endif
  29. //#define LOAD_MGMTAPI
  30. #ifdef LOAD_MGMTAPI
  31. #undef LOAD_MGMTAPI
  32. #endif
  33. #define LOAD_INETMIB1
  34. //#ifdef LOAD_INETMIB1
  35. //#undef LOAD_INETMIB1
  36. //#endif
  37. //
  38. // Disable DSIS interface for now
  39. //
  40. #ifdef USE_DSIS
  41. #undef USE_DSIS
  42. #endif
  43. //
  44. // Use IPHLPAPI.DLL
  45. //
  46. #ifndef USE_SNMP
  47. #define USE_IPHLPAPI
  48. #ifdef LOAD_INETMIB1
  49. #undef LOAD_INETMIB1
  50. #endif
  51. #endif
  52. //
  53. // Include Files
  54. //
  55. #include <nt.h>
  56. #include <ntrtl.h>
  57. #include <nturtl.h>
  58. #include <ntprfctr.h>
  59. #include <windows.h>
  60. #include <winperf.h>
  61. #include <winbase.h>
  62. #include <string.h>
  63. #include <stdlib.h>
  64. #include <stdio.h>
  65. #ifdef USE_SNMP
  66. #include <mgmtapi.h>
  67. #endif
  68. #include <snmp.h>
  69. #ifdef USE_IPHLPAPI
  70. #include <iphlpapi.h>
  71. #endif
  72. #include "perfctr.h" // error message definition
  73. #include "perfmsg.h"
  74. #include "perfutil.h"
  75. #include "perfnbt.h"
  76. //#include "perfdsis.h" ! not yet !
  77. #ifndef USE_IPHLPAPI
  78. #include "perftcp.h"
  79. #endif
  80. #include "datatcp.h"
  81. #define ALIGN_SIZE 0x00000008
  82. //
  83. // Global Variables
  84. //
  85. //
  86. // References to constants which initialize the Object type definitions
  87. //
  88. extern NET_INTERFACE_DATA_DEFINITION NetInterfaceDataDefinition;
  89. extern IP_DATA_DEFINITION IpDataDefinition;
  90. extern ICMP_DATA_DEFINITION IcmpDataDefinition;
  91. extern TCP_DATA_DEFINITION TcpDataDefinition;
  92. extern UDP_DATA_DEFINITION UdpDataDefinition;
  93. #ifndef USE_SNMP // only include if not using SNMP interface
  94. //
  95. HANDLE hSnmpEvent = NULL; // handler for SNMP Extension Agent
  96. #endif
  97. //
  98. // TCP/IP data structures
  99. //
  100. #ifdef USE_SNMP
  101. LPSNMP_MGR_SESSION TcpIpSession = (LPSNMP_MGR_SESSION) NULL;
  102. // The SNMP manager session providing
  103. // the requested information.
  104. #else
  105. BOOL TcpIpSession = FALSE;
  106. // The SNMP manager session providing
  107. // the requested information.
  108. #endif
  109. #ifdef USE_IPHLPAPI
  110. #define MAX_INTERFACE_LEN MAX_PATH // Maximum length of a network interface
  111. // name
  112. #define DEFAULT_INTERFACES 20 // Default interfaces count
  113. DWORD IfNum;
  114. MIB_IPSTATS IpStats;
  115. MIB_ICMP IcmpStats;
  116. MIB_TCPSTATS TcpStats;
  117. MIB_UDPSTATS UdpStats;
  118. PMIB_IFTABLE IfTable = NULL;
  119. DWORD IfTableSize = 0;
  120. #else
  121. AsnObjectName RefNames[NO_OF_OIDS];
  122. RFC1157VarBind RefVariableBindingsArray[NO_OF_OIDS],
  123. VariableBindingsArray[NO_OF_OIDS];
  124. // The array of the variable bindings,
  125. // used by the SNMP agent functions
  126. // to record the info we want for the
  127. // IP, ICMP, TCP and UDP protocols
  128. RFC1157VarBind IFPermVariableBindingsArray[NO_OF_IF_OIDS];
  129. // The initialization array of the
  130. // variable bindings,
  131. // used by the SNMP agent functions
  132. // to record the info we want for each
  133. // of the Network Interfaces
  134. RFC1157VarBindList RefVariableBindings;
  135. RFC1157VarBindList RefIFVariableBindings;
  136. RFC1157VarBindList RefVariableBindingsICMP;
  137. // The headers of the lists with the
  138. // variable bindings.
  139. // The headers of the lists with the
  140. // variable bindings.
  141. RFC1157VarBind NetIfRequest; // structure for net request
  142. RFC1157VarBindList NetIfRequestList;
  143. //
  144. // Constants
  145. //
  146. #define TIMEOUT 500 // Communication timeout in milliseconds
  147. #define RETRIES 5 // Communication time-out/retry count
  148. #define MAX_INTERFACE_LEN 10 // Maximum length of a network interface
  149. // name
  150. #define OIDS_OFFSET 0 // Offset of other than the ICMP Oids
  151. // in the VariableBindingsArray[]
  152. #define ICMP_OIDS_OFFSET 29 // Offset of the ICMP Oids in the array
  153. #define OIDS_LENGTH 29 // Number of the other than the ICMP
  154. // Oids in the VariableBindingsArray[]
  155. #define ICMP_OIDS_LENGTH 26 // Number of the ICMP Oids in the array
  156. //
  157. // Macro Definitions (To avoid long expressions)
  158. //
  159. #define IF_COUNTER(INDEX) \
  160. (IFVariableBindings.list[(INDEX)].value.asnValue.counter)
  161. #define IF_GAUGE(INDEX) \
  162. (IFVariableBindings.list[(INDEX)].value.asnValue.gauge)
  163. #define IP_COUNTER(INDEX) \
  164. (VariableBindings.list[(INDEX)].value.asnValue.counter)
  165. #define ICMP_COUNTER(INDEX) \
  166. (VariableBindingsICMP.list[(INDEX)].value.asnValue.counter)
  167. #define TCP_COUNTER(INDEX) \
  168. (VariableBindings.list[(INDEX)].value.asnValue.counter)
  169. #define UDP_COUNTER(INDEX) \
  170. (VariableBindings.list[(INDEX)].value.asnValue.counter)
  171. #define TCP_GAUGE(INDEX) \
  172. (VariableBindings.list[(INDEX)].value.asnValue.gauge)
  173. #endif
  174. #define TCP_OBJECT 0x00000001
  175. #define UDP_OBJECT 0x00000002
  176. #define IP_OBJECT 0x00000004
  177. #define ICMP_OBJECT 0x00000008
  178. #define NET_OBJECT 0x00000010
  179. #define NBT_OBJECT 0x00000020
  180. #define SNMP_OBJECTS (TCP_OBJECT+UDP_OBJECT+IP_OBJECT+ICMP_OBJECT+NET_OBJECT)
  181. #define SNMP_ERROR 0x40000000
  182. #define DO_COUNTER_OBJECT(flags,counter) \
  183. ((((flags) & (counter)) == (counter)) ? TRUE : FALSE)
  184. //
  185. // Function Prototypes
  186. //
  187. PM_OPEN_PROC OpenTcpIpPerformanceData;
  188. PM_COLLECT_PROC CollectTcpIpPerformanceData;
  189. PM_CLOSE_PROC CloseTcpIpPerformanceData;
  190. #ifdef LOAD_INETMIB1
  191. HANDLE hInetMibDll;
  192. PFNSNMPEXTENSIONINIT pSnmpExtensionInit;
  193. PFNSNMPEXTENSIONQUERY pSnmpExtensionQuery;
  194. #endif
  195. DWORD dwTcpRefCount = 0;
  196. static const WCHAR szFriendlyNetworkInterfaceNames[] = {L"FriendlyNetworkInterfaceNames"};
  197. static const WCHAR szTcpipPerformancePath[] = {L"SYSTEM\\CurrentControlSet\\Services\\TcpIp\\Performance"};
  198. static BOOL bUseFriendlyNames = FALSE;
  199. __inline Assign64(
  200. IN LONGLONG qwSrc,
  201. IN PLARGE_INTEGER pqwDest
  202. )
  203. {
  204. PLARGE_INTEGER pqwSrc = (PLARGE_INTEGER) &qwSrc;
  205. pqwDest->LowPart = pqwSrc->LowPart;
  206. pqwDest->HighPart = pqwSrc->HighPart;
  207. }
  208. static
  209. BOOL
  210. FriendlyNameIsSet ()
  211. {
  212. BOOL bReturn = TRUE;
  213. DWORD dwStatus = ERROR_SUCCESS;
  214. HKEY hKeyTcpipPerformance = NULL;
  215. DWORD dwType = 0;
  216. DWORD dwSize = 0;
  217. DWORD dwValue = 0;
  218. dwStatus = RegOpenKeyExW (
  219. HKEY_LOCAL_MACHINE,
  220. szTcpipPerformancePath,
  221. 0L,
  222. KEY_READ,
  223. &hKeyTcpipPerformance);
  224. if (dwStatus == ERROR_SUCCESS) {
  225. dwSize = sizeof(dwValue);
  226. dwStatus = RegQueryValueExW (
  227. hKeyTcpipPerformance,
  228. szFriendlyNetworkInterfaceNames,
  229. NULL,
  230. &dwType,
  231. (LPBYTE)&dwValue,
  232. &dwSize);
  233. if ((dwStatus == ERROR_SUCCESS) && (dwValue == 0) &&
  234. ((dwType == REG_DWORD) || ((dwType == REG_BINARY) && (dwSize == sizeof (DWORD))))) {
  235. bReturn = FALSE;
  236. }
  237. RegCloseKey (hKeyTcpipPerformance);
  238. }
  239. return bReturn;
  240. }
  241. DWORD
  242. OpenTcpIpPerformanceData (
  243. IN LPWSTR dwVoid // Argument needed only to conform to calling
  244. // interface for this routine. (NT > 312) RBW
  245. )
  246. /*++
  247. Routine Description:
  248. This routine will open all the TCP/IP devices and remember the handles
  249. returned by the devices.
  250. Arguments:
  251. IN LPWSTR dwVoid
  252. not used
  253. Return Value:
  254. ERROR_SUCCESS if successful completion
  255. error returned by OpenNbtPerformanceData
  256. error returned by OpenDsisPerformanceData
  257. or Win32 Error value
  258. --*/
  259. {
  260. DWORD Status;
  261. TCHAR ComputerName[MAX_COMPUTERNAME_LENGTH+1];
  262. DWORD cchBuffer = MAX_COMPUTERNAME_LENGTH+1;
  263. DWORD dwDataReturn[2]; // event log data
  264. #ifdef LOAD_INETMIB1
  265. UINT nErrorMode;
  266. #endif
  267. #ifndef USE_IPHLPAPI
  268. register i;
  269. #ifdef LOAD_MGMTAPI
  270. HANDLE hMgmtApiDll; // handle to library
  271. FARPROC SnmpMgrStrToOid; // address of function
  272. #else
  273. #define SnmpMgrStrToOid(a,b) SnmpMgrText2Oid((a),(b))
  274. #endif
  275. #ifdef LOAD_INETMIB1
  276. AsnObjectIdentifier SnmpOid;
  277. #endif
  278. #endif
  279. UNREFERENCED_PARAMETER (dwVoid);
  280. MonOpenEventLog ();
  281. REPORT_INFORMATION (TCP_OPEN_ENTERED, LOG_VERBOSE);
  282. HEAP_PROBE();
  283. if (dwTcpRefCount == 0) {
  284. // Open NBT
  285. Status = OpenNbtPerformanceData (0L);
  286. if ( Status != ERROR_SUCCESS ) {
  287. // NBT reports any Open errors to the user
  288. REPORT_ERROR (TCP_NBT_OPEN_FAIL, LOG_DEBUG);
  289. return Status;
  290. }
  291. REPORT_INFORMATION (TCP_NBT_OPEN_SUCCESS, LOG_VERBOSE);
  292. #ifdef USE_DSIS
  293. Status = OpenDsisPerformanceData (0L);
  294. if (Status != ERROR_SUCCESS) {
  295. // DSIS Open reports Open errors to the user
  296. REPORT_ERROR (TCP_DSIS_OPEN_FAIL, LOG_DEBUG);
  297. return (Status);
  298. }
  299. REPORT_INFORMATION (TCP_DSIS_OPEN_SUCCESS, LOG_VERBOSE);
  300. #endif // USE_DSIS
  301. #ifdef LOAD_MGMTAPI // this STILL craps out
  302. hMgmtApiDll = LoadLibrary ("MGMTAPI.DLL");
  303. if (hMgmtApiDll == NULL) {
  304. dwDataReturn[0] = GetLastError ();
  305. REPORT_ERROR_DATA (TCP_LOAD_LIBRARY_FAIL, LOG_USER,
  306. &dwDataReturn[0], (sizeof (DWORD)));
  307. return (dwDataReturn[0]);
  308. }
  309. SnmpMgrStrToOid = GetProcAddress (hMgmtApiDll, "SnmpMgrStrToOid");
  310. if (!(BOOL)SnmpMgrStrToOid) {
  311. dwDataReturn[0] = GetLastError();
  312. REPORT_ERROR_DATA (TCP_GET_STRTOOID_ADDR_FAIL, LOG_USER,
  313. &dwDataReturn[0], (sizeof (DWORD)));
  314. CloseNbtPerformanceData ();
  315. FreeLibrary (hMgmtApiDll);
  316. return (dwDataReturn[0]);
  317. }
  318. #else
  319. // SnmpMgrStrToOid is defined as a macro above
  320. #endif // LOAD_MGMTAPI
  321. #ifdef LOAD_INETMIB1 // this STILL craps out
  322. // don't pop up any dialog boxes
  323. nErrorMode = SetErrorMode (SEM_FAILCRITICALERRORS);
  324. hInetMibDll = LoadLibrary ("INETMIB1.DLL");
  325. if (hInetMibDll == NULL) {
  326. dwDataReturn[0] = GetLastError ();
  327. REPORT_ERROR_DATA (TCP_LOAD_LIBRARY_FAIL, LOG_USER,
  328. &dwDataReturn[0], (sizeof (DWORD)));
  329. CloseNbtPerformanceData ();
  330. // restore Error Mode
  331. SetErrorMode (nErrorMode);
  332. return (dwDataReturn[0]);
  333. } else {
  334. // restore Error Mode
  335. SetErrorMode (nErrorMode);
  336. }
  337. pSnmpExtensionInit = (PFNSNMPEXTENSIONINIT)GetProcAddress
  338. (hInetMibDll, "SnmpExtensionInit");
  339. pSnmpExtensionQuery = (PFNSNMPEXTENSIONQUERY)GetProcAddress
  340. (hInetMibDll, "SnmpExtensionQuery");
  341. if (!pSnmpExtensionInit || !pSnmpExtensionQuery) {
  342. dwDataReturn[0] = GetLastError();
  343. REPORT_ERROR_DATA (TCP_LOAD_ROUTINE_FAIL, LOG_USER,
  344. &dwDataReturn[0], (sizeof (DWORD)));
  345. FreeLibrary (hInetMibDll);
  346. CloseNbtPerformanceData ();
  347. return (dwDataReturn[0]);
  348. }
  349. #endif // LOAD_INETMIB1
  350. // Initialize the Variable Binding list for IP, ICMP, TCP and UDP
  351. Status = 0; // initialize error count
  352. HEAP_PROBE();
  353. #ifndef USE_IPHLPAPI
  354. for (i = 0; i < NO_OF_OIDS; i++) {
  355. if (!SnmpMgrStrToOid (OidStr[i], &(RefNames[i]))) {
  356. Status++;
  357. REPORT_ERROR_DATA (TCP_BAD_OBJECT, LOG_DEBUG,
  358. OidStr[i], strlen(OidStr[i]));
  359. RefNames[i].ids = NULL;
  360. RefNames[i].idLength = 0;
  361. }
  362. RefVariableBindingsArray[i].value.asnType = ASN_NULL;
  363. }
  364. if (Status == 0) {
  365. REPORT_INFORMATION (TCP_BINDINGS_INIT, LOG_VERBOSE);
  366. }
  367. HEAP_PROBE();
  368. // Initialize the Variable Binding list for Network interfaces
  369. Status = 0;
  370. for (i = 0; i < NO_OF_IF_OIDS; i++) {
  371. if (!SnmpMgrStrToOid (IfOidStr[i], &(IFPermVariableBindingsArray[i].name))) {
  372. Status++;
  373. REPORT_ERROR_DATA (TCP_BAD_OBJECT, LOG_DEBUG,
  374. IfOidStr[i], strlen(IfOidStr[i]));
  375. }
  376. IFPermVariableBindingsArray[i].value.asnType = ASN_NULL;
  377. }
  378. HEAP_PROBE();
  379. #ifdef LOAD_MGMTAPI
  380. FreeLibrary (hMgmtApiDll); // done with SnmpMgrStrToOid routine
  381. #endif
  382. // initialize list structures
  383. RefVariableBindings.list = RefVariableBindingsArray + OIDS_OFFSET;
  384. RefVariableBindings.len = OIDS_LENGTH;
  385. RefVariableBindingsICMP.list =
  386. RefVariableBindingsArray + ICMP_OIDS_OFFSET;
  387. RefVariableBindingsICMP.len = ICMP_OIDS_LENGTH;
  388. RefIFVariableBindings.list = IFPermVariableBindingsArray;
  389. RefIFVariableBindings.len = NO_OF_IF_OIDS;
  390. #endif
  391. if ( GetComputerName ((LPTSTR)ComputerName, (LPDWORD)&cchBuffer) == FALSE ) {
  392. dwDataReturn[0] = GetLastError();
  393. dwDataReturn[1] = 0;
  394. REPORT_ERROR_DATA (TCP_COMPUTER_NAME, LOG_USER,
  395. &dwDataReturn, sizeof(dwDataReturn));
  396. CloseNbtPerformanceData ();
  397. return dwDataReturn[0];
  398. }
  399. #ifdef USE_IPHLPAPI
  400. // enforce that TcpIpSession is on.
  401. //
  402. TcpIpSession = TRUE;
  403. #else
  404. #ifdef USE_SNMP
  405. // Establish the SNMP connection to communicate with the local SNMP agent
  406. /* This portion of the code for OpenTcpIpPerformanceData() could be used in
  407. the CollectTcpIpPerformanceData() routine to open an SNMP Manager session
  408. and collect data for the Network Interfaces, and IP, ICMP, TCP and UDP
  409. protocols for a remote machine.
  410. So, name this portion of the code: A
  411. */
  412. if ( (TcpIpSession = SnmpMgrOpen ((LPSTR) ComputerName,
  413. (LPSTR) "public",
  414. TIMEOUT,
  415. RETRIES)) == NULL ) {
  416. dwDataReturn[0] = GetLastError();
  417. REPORT_ERROR_DATA (TCP_SNMP_MGR_OPEN, LOG_USER,
  418. &dwDataReturn, sizeof(DWORD));
  419. return dwDataReturn[0];
  420. }
  421. /* End of code A
  422. */
  423. #else
  424. // if not using the standard SNMP interface, then TcpIpSession is
  425. // a "boolean" to indicate if a session has been initialized and
  426. // can therefore be used
  427. TcpIpSession = FALSE; // make sure it's FALSE
  428. // initialize inet mib routines
  429. Status = (*pSnmpExtensionInit)(
  430. 0L,
  431. &hSnmpEvent, // event is created by Init Routine
  432. &SnmpOid
  433. );
  434. if (Status) {
  435. TcpIpSession = TRUE; // return TRUE to indicate OK
  436. }
  437. #endif // USE_SNMP
  438. #endif
  439. bUseFriendlyNames = FriendlyNameIsSet();
  440. }
  441. dwTcpRefCount++;
  442. HEAP_PROBE();
  443. REPORT_INFORMATION (TCP_OPEN_PERFORMANCE_DATA, LOG_DEBUG);
  444. return ERROR_SUCCESS;
  445. } // OpenTcpIpPerformanceData
  446. #pragma warning ( disable : 4127)
  447. DWORD
  448. CollectTcpIpPerformanceData(
  449. LPWSTR lpValueName,
  450. LPVOID *lppData,
  451. LPDWORD lpcbTotalBytes,
  452. LPDWORD lpNumObjectTypes
  453. )
  454. /*++
  455. Routine Description:
  456. This routine will return the data for all the TCP/IP counters.
  457. Arguments:
  458. Pointer to unicode string which is value passed to the registry for the
  459. query.
  460. Pointer to pointer to where to place the data.
  461. Size in bytes of the data buffer.
  462. Return Value:
  463. Win32 Status. If successful, pointer to where to place the data
  464. will be set to location following this routine's returned data block.
  465. --*/
  466. {
  467. DWORD Status;
  468. // Variables for reformatting the TCP/IP data
  469. register PDWORD pdwCounter, pdwPackets;
  470. NET_INTERFACE_DATA_DEFINITION *pNetInterfaceDataDefinition;
  471. IP_DATA_DEFINITION *pIpDataDefinition;
  472. ICMP_DATA_DEFINITION *pIcmpDataDefinition;
  473. TCP_DATA_DEFINITION *pTcpDataDefinition;
  474. UDP_DATA_DEFINITION *pUdpDataDefinition;
  475. DWORD SpaceNeeded;
  476. UNICODE_STRING InterfaceName;
  477. ANSI_STRING AnsiInterfaceName;
  478. WCHAR InterfaceNameBuffer[MAX_INTERFACE_LEN+1];
  479. CHAR AnsiInterfaceNameBuffer[MAX_INTERFACE_LEN+1];
  480. register PERF_INSTANCE_DEFINITION *pPerfInstanceDefinition;
  481. PERF_COUNTER_BLOCK *pPerfCounterBlock;
  482. LPVOID lpDataTemp;
  483. DWORD NumObjectTypesTemp;
  484. LPWSTR lpFromString;
  485. DWORD dwQueryType;
  486. DWORD dwCounterFlags;
  487. DWORD dwThisChar;
  488. DWORD dwBlockSize;
  489. // Variables for collecting the TCP/IP data
  490. AsnInteger ErrorStatus;
  491. AsnInteger ErrorIndex;
  492. AsnInteger NetInterfaces;
  493. AsnInteger Interface;
  494. DWORD SentTemp;
  495. DWORD ReceivedTemp;
  496. DWORD dwDataReturn[2]; // for error values
  497. BOOL bFreeName;
  498. #ifndef USE_IPHLPAPI
  499. int i;
  500. BOOL bStatus;
  501. #if USE_SNMP
  502. RFC1157VarBind IFVariableBindingsArray[NO_OF_IF_OIDS];
  503. // The array of the variable bindings,
  504. // used by the SNMP agent functions
  505. // to record the info we want for each
  506. // of the Network Interfaces
  507. RFC1157VarBind *VBElem;
  508. AsnInteger VBItem;
  509. #endif
  510. RFC1157VarBindList IFVariableBindings,
  511. IFVariableBindingsCall,
  512. VariableBindings,
  513. VariableBindingsICMP;
  514. // The header of the above list with
  515. // the variable bindings.
  516. #endif
  517. //
  518. // ***************** executable code starts here *******************
  519. //
  520. ErrorStatus = 0L;
  521. ErrorIndex = 0L;
  522. if (lpValueName == NULL) {
  523. REPORT_INFORMATION (TCP_COLLECT_ENTERED, LOG_VERBOSE);
  524. } else {
  525. REPORT_INFORMATION_DATA (TCP_COLLECT_ENTERED, LOG_VERBOSE,
  526. (LPVOID)lpValueName, (DWORD)(lstrlenW(lpValueName)*sizeof(WCHAR)));
  527. }
  528. //
  529. // IF_DATA are all in DWORDS. We need to allow 1 of the octets which
  530. // will be __int64
  531. //
  532. dwBlockSize = SIZE_OF_IF_DATA + (1 * sizeof(DWORD));
  533. HEAP_PROBE();
  534. //
  535. // before doing anything else,
  536. // see if this is a foreign (i.e. non-NT) computer data request
  537. //
  538. dwQueryType = GetQueryType (lpValueName);
  539. if (dwQueryType == QUERY_FOREIGN) {
  540. // find start of computer name to pass to CollectDsisPerformanceData
  541. // this should put the pointer at the first character after the space
  542. // presumably the computer name
  543. lpFromString = lpValueName +
  544. ((sizeof(L"Foreign ")/sizeof(WCHAR))+1);
  545. // check for double slash notation and move past if found
  546. while (*lpFromString == '\\') {
  547. lpFromString++;
  548. }
  549. //
  550. // initialize local variables for sending to CollectDsisPerformanceData
  551. // routine
  552. //
  553. lpDataTemp = *lppData;
  554. SpaceNeeded = *lpcbTotalBytes;
  555. NumObjectTypesTemp = *lpNumObjectTypes;
  556. REPORT_INFORMATION_DATA (TCP_FOREIGN_COMPUTER_CMD, LOG_VERBOSE,
  557. (LPVOID)lpFromString, (DWORD)(lstrlenW(lpFromString)*sizeof(WCHAR)));
  558. #ifdef USE_DSIS
  559. Status = CollectDsisPerformanceData (
  560. lpFromString,
  561. (LPVOID *) &lpDataTemp,
  562. (LPDWORD) &SpaceNeeded,
  563. (LPDWORD) &NumObjectTypesTemp);
  564. //
  565. // look at returned arguments to see if an error occured
  566. // and send the appropriate event to the event log
  567. //
  568. if (Status == ERROR_SUCCESS) {
  569. if (NumObjectTypesTemp > 0) {
  570. REPORT_INFORMATION_DATA (TCP_DSIS_COLLECT_DATA_SUCCESS, LOG_DEBUG,
  571. &NumObjectTypesTemp, sizeof (NumObjectTypesTemp));
  572. } else {
  573. REPORT_ERROR (TCP_DSIS_NO_OBJECTS, LOG_DEBUG);
  574. }
  575. //
  576. // update main return variables
  577. //
  578. *lppData = ALIGN_ON_QWORD(lpDataTemp);
  579. *lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
  580. *lpNumObjectTypes = NumObjectTypesTemp;
  581. return ERROR_SUCCESS;
  582. } else {
  583. REPORT_ERROR_DATA (TCP_DSIS_COLLECT_DATA_ERROR, LOG_DEBUG,
  584. &Status, sizeof (Status));
  585. *lpcbTotalBytes = 0;
  586. *lpNumObjectTypes = 0;
  587. return Status;
  588. }
  589. #else
  590. // no foreign data interface supported
  591. *lpcbTotalBytes = 0;
  592. *lpNumObjectTypes = 0;
  593. return ERROR_SUCCESS;
  594. #endif // USE_DSIS
  595. } // endif QueryType == Foreign
  596. dwCounterFlags = 0;
  597. // determine what to return
  598. if (dwQueryType == QUERY_GLOBAL) {
  599. dwCounterFlags |= NBT_OBJECT;
  600. dwCounterFlags |= SNMP_OBJECTS;
  601. } else if (dwQueryType == QUERY_ITEMS) {
  602. // check for the items provided by this routine
  603. //
  604. // Since the data requests for the following protocols are all
  605. // bundled together, we'll send back all the data. Collecting it
  606. // via SNMP is the hard part. once that's done, sending it back
  607. // is trivial.
  608. //
  609. if (IsNumberInUnicodeList (TCP_OBJECT_TITLE_INDEX, lpValueName)) {
  610. dwCounterFlags |= SNMP_OBJECTS;
  611. } else if (IsNumberInUnicodeList (UDP_OBJECT_TITLE_INDEX, lpValueName)) {
  612. dwCounterFlags |= SNMP_OBJECTS;
  613. } else if (IsNumberInUnicodeList (IP_OBJECT_TITLE_INDEX, lpValueName)) {
  614. dwCounterFlags |= SNMP_OBJECTS;
  615. } else if (IsNumberInUnicodeList (ICMP_OBJECT_TITLE_INDEX, lpValueName)) {
  616. dwCounterFlags |= SNMP_OBJECTS;
  617. } else if (IsNumberInUnicodeList (NET_OBJECT_TITLE_INDEX, lpValueName)) {
  618. dwCounterFlags |= SNMP_OBJECTS;
  619. }
  620. if (IsNumberInUnicodeList (NBT_OBJECT_TITLE_INDEX, lpValueName)) {
  621. dwCounterFlags |= NBT_OBJECT;
  622. }
  623. }
  624. #ifndef USE_IPHLPAPI
  625. // copy Binding array structures to working buffers for Snmp queries
  626. RtlMoveMemory (VariableBindingsArray,
  627. RefVariableBindingsArray,
  628. sizeof (RefVariableBindingsArray));
  629. VariableBindings.list = VariableBindingsArray + OIDS_OFFSET;
  630. VariableBindings.len = OIDS_LENGTH;
  631. VariableBindingsICMP.list = VariableBindingsArray + ICMP_OIDS_OFFSET;
  632. VariableBindingsICMP.len = ICMP_OIDS_LENGTH;
  633. #endif
  634. if (DO_COUNTER_OBJECT (dwCounterFlags, NBT_OBJECT)) {
  635. // Copy the parameters. We'll call the NBT Collect routine with these
  636. // parameters
  637. lpDataTemp = *lppData;
  638. SpaceNeeded = *lpcbTotalBytes;
  639. NumObjectTypesTemp = *lpNumObjectTypes;
  640. // Collect NBT data
  641. Status = CollectNbtPerformanceData (lpValueName,
  642. (LPVOID *) &lpDataTemp,
  643. (LPDWORD) &SpaceNeeded,
  644. (LPDWORD) &NumObjectTypesTemp) ;
  645. if (Status != ERROR_SUCCESS) {
  646. // NBT Collection routine logs error messages to user
  647. REPORT_ERROR_DATA (TCP_NBT_COLLECT_DATA, LOG_DEBUG,
  648. &Status, sizeof (Status));
  649. *lpcbTotalBytes = 0L;
  650. *lpNumObjectTypes = 0L;
  651. return Status;
  652. }
  653. } else {
  654. // Initialize the parameters. We'll use these local
  655. // parameters for remaining routines if NBT didn't use them
  656. lpDataTemp = *lppData;
  657. SpaceNeeded = 0;
  658. NumObjectTypesTemp = 0;
  659. }
  660. /* To collect data for the Network Interfaces, and IP, ICMP, TCP and UDP
  661. protocols for a remote machine whose name is in the Unicode string pointed
  662. to by the lpValueName argument of CollectTcpIpData() routine, modify the
  663. routine as follows:
  664. 1. Remove all the Nbt stuff from the code.
  665. 2. Convert the remote machine name from Unicode to Ansi, and have a local
  666. LPSTR variable pointing to the Ansi remote machine name.
  667. 3. Place the above portion of the code named A after this comment.
  668. 4. Place the code named B (which is at the end of the file) at the end
  669. of this routine to close the opened SNMP session.
  670. */
  671. // get network info from SNMP agent
  672. if ((dwCounterFlags & SNMP_OBJECTS) > 0) { // if any SNMP Objects selected
  673. if (TRUE) { // and not a skeleton request
  674. #ifdef USE_SNMP
  675. if ( TcpIpSession == (LPSNMP_MGR_SESSION) NULL ) {
  676. REPORT_WARNING (TCP_NULL_SESSION, LOG_DEBUG);
  677. *lppData = ALIGN_ON_QWORD(lpDataTemp);
  678. *lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
  679. *lpNumObjectTypes = NumObjectTypesTemp;
  680. return ERROR_SUCCESS;
  681. }
  682. #else
  683. if (!TcpIpSession) {
  684. REPORT_WARNING (TCP_NULL_SESSION, LOG_DEBUG);
  685. *lppData = ALIGN_ON_QWORD(lpDataTemp);
  686. *lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
  687. *lpNumObjectTypes = NumObjectTypesTemp;
  688. return ERROR_SUCCESS;
  689. }
  690. #endif
  691. // Get the data for the IP, ICMP, TCP and UDP protocols, as well as
  692. // the number of existing network interfaces.
  693. // create local query list
  694. HEAP_PROBE();
  695. #ifdef USE_IPHLPAPI
  696. Status = GetNumberOfInterfaces(&IfNum);
  697. if (Status)
  698. {
  699. dwDataReturn[0] = Status;
  700. dwDataReturn[1] = 0;
  701. REPORT_ERROR_DATA (TCP_SNMP_MGR_REQUEST, LOG_DEBUG,
  702. &dwDataReturn, sizeof(dwDataReturn));
  703. *lppData = ALIGN_ON_QWORD(lpDataTemp);
  704. *lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
  705. *lpNumObjectTypes = NumObjectTypesTemp;
  706. return ERROR_SUCCESS;
  707. }
  708. Status = GetIpStatistics(&IpStats);
  709. if (Status)
  710. {
  711. dwDataReturn[0] = Status;
  712. dwDataReturn[1] = 0;
  713. REPORT_ERROR_DATA (TCP_SNMP_MGR_REQUEST, LOG_DEBUG,
  714. &dwDataReturn, sizeof(dwDataReturn));
  715. *lppData = ALIGN_ON_QWORD(lpDataTemp);
  716. *lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
  717. *lpNumObjectTypes = NumObjectTypesTemp;
  718. return ERROR_SUCCESS;
  719. }
  720. Status = GetTcpStatistics(&TcpStats);
  721. if (Status)
  722. {
  723. dwDataReturn[0] = Status;
  724. dwDataReturn[1] = 0;
  725. REPORT_ERROR_DATA (TCP_SNMP_MGR_REQUEST, LOG_DEBUG,
  726. &dwDataReturn, sizeof(dwDataReturn));
  727. *lppData = ALIGN_ON_QWORD(lpDataTemp);
  728. *lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
  729. *lpNumObjectTypes = NumObjectTypesTemp;
  730. return ERROR_SUCCESS;
  731. }
  732. Status = GetUdpStatistics(&UdpStats);
  733. if (Status)
  734. {
  735. dwDataReturn[0] = Status;
  736. dwDataReturn[1] = 0;
  737. REPORT_ERROR_DATA (TCP_SNMP_MGR_REQUEST, LOG_DEBUG,
  738. &dwDataReturn, sizeof(dwDataReturn));
  739. *lppData = ALIGN_ON_QWORD(lpDataTemp);
  740. *lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
  741. *lpNumObjectTypes = NumObjectTypesTemp;
  742. return ERROR_SUCCESS;
  743. }
  744. Status = GetIcmpStatistics(&IcmpStats);
  745. if (Status)
  746. {
  747. dwDataReturn[0] = Status;
  748. dwDataReturn[1] = 0;
  749. REPORT_ERROR_DATA (TCP_ICMP_REQUEST, LOG_DEBUG,
  750. &dwDataReturn, sizeof(dwDataReturn));
  751. *lppData = ALIGN_ON_QWORD(lpDataTemp);
  752. *lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
  753. *lpNumObjectTypes = NumObjectTypesTemp;
  754. return ERROR_SUCCESS;
  755. }
  756. HEAP_PROBE();
  757. } // endif (TRUE)
  758. #else
  759. #ifdef USE_SNMP
  760. SnmpUtilVarBindListCpy (&VariableBindings,
  761. &RefVariableBindings);
  762. #else
  763. for (i = 0; i < NO_OF_OIDS; i++) {
  764. SnmpUtilOidCpy (&(RefVariableBindingsArray[i].name),
  765. &(RefNames[i]));
  766. }
  767. VariableBindings.list = RtlAllocateHeap (
  768. RtlProcessHeap(),
  769. 0L,
  770. (RefVariableBindings.len * sizeof(RFC1157VarBind)));
  771. if (!VariableBindings.list) {
  772. REPORT_ERROR (TCP_SNMP_BUFFER_ALLOC_FAIL, LOG_DEBUG);
  773. *lppData = ALIGN_ON_QWORD(lpDataTemp);
  774. *lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
  775. *lpNumObjectTypes = NumObjectTypesTemp;
  776. return ERROR_SUCCESS;
  777. } else {
  778. RtlMoveMemory (
  779. VariableBindings.list,
  780. RefVariableBindings.list,
  781. (RefVariableBindings.len * sizeof(RFC1157VarBind)));
  782. VariableBindings.len = RefVariableBindings.len;
  783. }
  784. #endif
  785. HEAP_PROBE();
  786. #ifdef USE_SNMP
  787. bStatus = SnmpMgrRequest (TcpIpSession,
  788. ASN_RFC1157_GETREQUEST,
  789. &VariableBindings,
  790. &ErrorStatus,
  791. &ErrorIndex);
  792. #else
  793. bStatus = (*pSnmpExtensionQuery) (ASN_RFC1157_GETREQUEST,
  794. &VariableBindings,
  795. &ErrorStatus,
  796. &ErrorIndex);
  797. #endif
  798. if ( !bStatus ) {
  799. dwDataReturn[0] = ErrorStatus;
  800. dwDataReturn[1] = ErrorIndex;
  801. REPORT_ERROR_DATA (TCP_SNMP_MGR_REQUEST, LOG_DEBUG,
  802. &dwDataReturn, sizeof(dwDataReturn));
  803. *lppData = ALIGN_ON_QWORD(lpDataTemp);
  804. *lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
  805. *lpNumObjectTypes = NumObjectTypesTemp;
  806. SnmpUtilVarBindListFree (&VariableBindings);
  807. return ERROR_SUCCESS;
  808. }
  809. if ( ErrorStatus > 0 ) {
  810. dwDataReturn[0] = ErrorStatus;
  811. dwDataReturn[1] = ErrorIndex;
  812. REPORT_ERROR_DATA (TCP_SNMP_MGR_REQUEST, LOG_DEBUG,
  813. &dwDataReturn, sizeof(dwDataReturn));
  814. *lppData = ALIGN_ON_QWORD(lpDataTemp);
  815. *lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
  816. *lpNumObjectTypes = NumObjectTypesTemp;
  817. SnmpUtilVarBindListFree (&VariableBindings);
  818. return ERROR_SUCCESS;
  819. }
  820. HEAP_PROBE();
  821. #ifdef USE_SNMP
  822. SnmpUtilVarBindListCpy (&VariableBindingsICMP,
  823. &RefVariableBindingsICMP);
  824. #else
  825. VariableBindingsICMP.list = RtlAllocateHeap (
  826. RtlProcessHeap(),
  827. 0L,
  828. (RefVariableBindingsICMP.len * sizeof(RFC1157VarBind)));
  829. if (!VariableBindingsICMP.list) {
  830. REPORT_ERROR (TCP_SNMP_BUFFER_ALLOC_FAIL, LOG_DEBUG);
  831. *lppData = ALIGN_ON_QWORD(lpDataTemp);
  832. *lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded;
  833. *lpNumObjectTypes = NumObjectTypesTemp;
  834. return ERROR_SUCCESS;
  835. } else {
  836. RtlMoveMemory (
  837. VariableBindingsICMP.list,
  838. RefVariableBindingsICMP.list,
  839. (RefVariableBindingsICMP.len * sizeof(RFC1157VarBind)));
  840. VariableBindingsICMP.len = RefVariableBindingsICMP.len;
  841. }
  842. #endif
  843. HEAP_PROBE();
  844. #ifdef USE_SNMP
  845. bStatus = SnmpMgrRequest (TcpIpSession,
  846. ASN_RFC1157_GETREQUEST,
  847. &VariableBindingsICMP,
  848. &ErrorStatus,
  849. #else
  850. bStatus = (*pSnmpExtensionQuery) (ASN_RFC1157_GETREQUEST,
  851. &VariableBindingsICMP,
  852. &ErrorStatus,
  853. &ErrorIndex);
  854. #endif
  855. if ( !bStatus ) {
  856. dwDataReturn[0] = ErrorStatus;
  857. dwDataReturn[1] = ErrorIndex;
  858. REPORT_ERROR_DATA (TCP_ICMP_REQUEST, LOG_DEBUG,
  859. &dwDataReturn, sizeof(dwDataReturn));
  860. *lppData = ALIGN_ON_QWORD(lpDataTemp);
  861. *lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
  862. *lpNumObjectTypes = NumObjectTypesTemp;
  863. SnmpUtilVarBindListFree (&VariableBindings);
  864. SnmpUtilVarBindListFree (&VariableBindingsICMP);
  865. return ERROR_SUCCESS;
  866. }
  867. if ( ErrorStatus > 0 ) {
  868. dwDataReturn[0] = ErrorStatus;
  869. dwDataReturn[1] = ErrorIndex;
  870. REPORT_ERROR_DATA (TCP_ICMP_REQUEST, LOG_DEBUG,
  871. &dwDataReturn, sizeof(dwDataReturn));
  872. *lppData = ALIGN_ON_QWORD(lpDataTemp);
  873. *lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
  874. *lpNumObjectTypes = NumObjectTypesTemp;
  875. SnmpUtilVarBindListFree (&VariableBindings);
  876. SnmpUtilVarBindListFree (&VariableBindingsICMP);
  877. return ERROR_SUCCESS;
  878. }
  879. } // endif (TRUE)
  880. HEAP_PROBE();
  881. // make sure everything made it back OK
  882. if (VariableBindingsICMP.list == 0) {
  883. REPORT_WARNING (TCP_NULL_ICMP_BUFF, LOG_DEBUG);
  884. dwCounterFlags |= (SNMP_ERROR); // return null data
  885. }
  886. if (VariableBindings.list == 0) {
  887. REPORT_WARNING (TCP_NULL_TCP_BUFF, LOG_DEBUG);
  888. dwCounterFlags |= (SNMP_ERROR); // return null data
  889. dwCounterFlags &= ~NET_OBJECT; // don't do NET Interface ctrs.
  890. }
  891. #endif
  892. if (DO_COUNTER_OBJECT(dwCounterFlags, SNMP_ERROR)) {
  893. REPORT_WARNING (TCP_NULL_SNMP_BUFF, LOG_USER);
  894. }
  895. if (DO_COUNTER_OBJECT (dwCounterFlags, NET_OBJECT)) {
  896. SpaceNeeded += sizeof (NET_INTERFACE_DATA_DEFINITION);
  897. if ( *lpcbTotalBytes < SpaceNeeded ) {
  898. dwDataReturn[0] = *lpcbTotalBytes;
  899. dwDataReturn[1] = SpaceNeeded;
  900. REPORT_WARNING_DATA (TCP_NET_IF_BUFFER_SIZE, LOG_DEBUG,
  901. &dwDataReturn, sizeof(dwDataReturn));
  902. //
  903. // if the buffer size is too small here, throw everything
  904. // away (including the NBT stuff) and return buffer size
  905. // error. If all goes well the caller will call back shortly
  906. // with a larger buffer and everything will be re-collected.
  907. //
  908. *lpcbTotalBytes = 0;
  909. *lpNumObjectTypes = 0;
  910. #ifndef USE_IPHLPAPI
  911. SnmpUtilVarBindListFree (&VariableBindings);
  912. SnmpUtilVarBindListFree (&VariableBindingsICMP);
  913. #endif
  914. return ERROR_MORE_DATA;
  915. }
  916. pNetInterfaceDataDefinition =
  917. (NET_INTERFACE_DATA_DEFINITION *) lpDataTemp;
  918. RtlMoveMemory (pNetInterfaceDataDefinition,
  919. &NetInterfaceDataDefinition,
  920. sizeof (NET_INTERFACE_DATA_DEFINITION));
  921. pPerfInstanceDefinition = (PERF_INSTANCE_DEFINITION *)
  922. (pNetInterfaceDataDefinition + 1);
  923. #ifdef USE_IPHLPAPI
  924. NetInterfaces = IfNum;
  925. #else
  926. NetInterfaces =
  927. VariableBindings.list[IF_NUMBER_INDEX].value.asnValue.number;
  928. #endif
  929. REPORT_INFORMATION_DATA (TCP_NET_INTERFACE, LOG_VERBOSE,
  930. &NetInterfaces, sizeof(NetInterfaces));
  931. if ( NetInterfaces ) {
  932. // Initialize the Variable Binding list for the
  933. // Network Interface Performance Data
  934. #ifndef USE_IPHLPAPI
  935. HEAP_PROBE();
  936. #ifdef USE_SNMP
  937. SnmpUtilVarBindListCpy (&IFVariableBindings,
  938. &RefIFVariableBindings);
  939. #else
  940. SnmpUtilVarBindListCpy (&IFVariableBindingsCall,
  941. &RefIFVariableBindings);
  942. IFVariableBindings.list = RtlAllocateHeap (
  943. RtlProcessHeap(),
  944. 0L,
  945. (RefIFVariableBindings.len * sizeof(RFC1157VarBind)));
  946. if (!IFVariableBindings.list) {
  947. REPORT_ERROR (TCP_SNMP_BUFFER_ALLOC_FAIL, LOG_DEBUG);
  948. *lppData = ALIGN_ON_QWORD(lpDataTemp);
  949. *lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
  950. *lpNumObjectTypes = NumObjectTypesTemp;
  951. return ERROR_SUCCESS;
  952. } else {
  953. RtlMoveMemory (
  954. IFVariableBindings.list,
  955. IFVariableBindingsCall.list,
  956. (IFVariableBindingsCall.len * sizeof(RFC1157VarBind)));
  957. IFVariableBindings.len = RefIFVariableBindings.len;
  958. }
  959. #endif
  960. #endif
  961. HEAP_PROBE();
  962. // Initialize buffer for the network interfaces' names
  963. AnsiInterfaceName.Length =
  964. AnsiInterfaceName.MaximumLength = MAX_INTERFACE_LEN + 1;
  965. AnsiInterfaceName.Buffer = AnsiInterfaceNameBuffer;
  966. }
  967. #ifdef USE_IPHLPAPI
  968. Status = GetNumberOfInterfaces(&NetInterfaces);
  969. if ((Status != ERROR_SUCCESS) || (NetInterfaces < DEFAULT_INTERFACES)) {
  970. NetInterfaces = DEFAULT_INTERFACES;
  971. }
  972. IfTableSize = SIZEOF_IFTABLE(NetInterfaces);
  973. Status = ERROR_INSUFFICIENT_BUFFER;
  974. SentTemp = 0;
  975. IfTable = NULL;
  976. while ((Status == ERROR_INSUFFICIENT_BUFFER) &&
  977. (SentTemp++ < 10)) {
  978. if (IfTable) {
  979. HeapFree(RtlProcessHeap(), 0L, IfTable);
  980. }
  981. IfTable = (PMIB_IFTABLE) RtlAllocateHeap(
  982. RtlProcessHeap(), 0L, IfTableSize);
  983. if (!IfTable)
  984. {
  985. REPORT_ERROR (TCP_SNMP_BUFFER_ALLOC_FAIL, LOG_DEBUG);
  986. *lppData = ALIGN_ON_QWORD(lpDataTemp);
  987. *lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
  988. *lpNumObjectTypes = NumObjectTypesTemp;
  989. return ERROR_SUCCESS;
  990. }
  991. Status = GetIfTable(IfTable, & IfTableSize, FALSE);
  992. }
  993. if (Status)
  994. {
  995. dwDataReturn[0] = Status;
  996. dwDataReturn[1] = 0;
  997. REPORT_ERROR_DATA (TCP_NET_GETNEXT_REQUEST, LOG_DEBUG,
  998. &dwDataReturn, sizeof(dwDataReturn));
  999. #ifdef USE_IPHLPAPI
  1000. if (IfTable) {
  1001. RtlFreeHeap(RtlProcessHeap(), 0L, IfTable);
  1002. IfTable = NULL;
  1003. }
  1004. #endif
  1005. *lppData = ALIGN_ON_QWORD(lpDataTemp);
  1006. *lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
  1007. *lpNumObjectTypes = NumObjectTypesTemp;
  1008. return ERROR_SUCCESS;
  1009. }
  1010. NetInterfaces = IfTable->dwNumEntries;
  1011. #endif
  1012. // Loop for every network interface
  1013. for ( Interface = 0; Interface < NetInterfaces; Interface++ ) {
  1014. // Get the data for the network interface
  1015. HEAP_PROBE();
  1016. #ifndef USE_IPHLPAPI
  1017. #ifdef USE_SNMP
  1018. bStatus = SnmpMgrRequest ( TcpIpSession,
  1019. ASN_RFC1157_GETNEXTREQUEST,
  1020. &IFVariableBindings,
  1021. &ErrorStatus,
  1022. &ErrorIndex);
  1023. #else
  1024. bStatus = (*pSnmpExtensionQuery) (ASN_RFC1157_GETNEXTREQUEST,
  1025. &IFVariableBindings,
  1026. &ErrorStatus,
  1027. &ErrorIndex);
  1028. #endif
  1029. HEAP_PROBE();
  1030. if ( ! bStatus ) {
  1031. continue;
  1032. }
  1033. if ( ErrorStatus > 0 ) {
  1034. dwDataReturn[0] = ErrorStatus;
  1035. dwDataReturn[1] = ErrorIndex;
  1036. REPORT_ERROR_DATA (TCP_NET_GETNEXT_REQUEST, LOG_DEBUG,
  1037. &dwDataReturn, sizeof(dwDataReturn));
  1038. continue;
  1039. }
  1040. #endif
  1041. bFreeName = FALSE;
  1042. // Everything is fine, so go get the data (prepare a new instance)
  1043. #ifdef USE_IPHLPAPI
  1044. RtlInitAnsiString(&AnsiInterfaceName, IfTable->table[Interface].bDescr);
  1045. #else
  1046. AnsiInterfaceName.Length = (USHORT)sprintf (AnsiInterfaceNameBuffer,
  1047. "%ld",
  1048. IFVariableBindings.list[IF_INDEX_INDEX].value.asnValue.number);
  1049. #endif
  1050. if (AnsiInterfaceName.Length <= MAX_INTERFACE_LEN) {
  1051. RtlInitUnicodeString(&InterfaceName, NULL);
  1052. RtlAnsiStringToUnicodeString(
  1053. &InterfaceName,
  1054. &AnsiInterfaceName,
  1055. TRUE);
  1056. bFreeName = TRUE;
  1057. }
  1058. else {
  1059. InterfaceName.Length =
  1060. InterfaceName.MaximumLength = (MAX_INTERFACE_LEN + 1) * sizeof (WCHAR);
  1061. InterfaceName.Buffer = InterfaceNameBuffer;
  1062. RtlAnsiStringToUnicodeString (&InterfaceName,
  1063. &AnsiInterfaceName,
  1064. FALSE);
  1065. }
  1066. SpaceNeeded += sizeof (PERF_INSTANCE_DEFINITION) +
  1067. QWORD_MULTIPLE(InterfaceName.Length+sizeof(UNICODE_NULL)) +
  1068. dwBlockSize;
  1069. if ( *lpcbTotalBytes < SpaceNeeded ) {
  1070. dwDataReturn[0] = *lpcbTotalBytes;
  1071. dwDataReturn[1] = SpaceNeeded;
  1072. REPORT_WARNING_DATA (TCP_NET_BUFFER_SIZE, LOG_DEBUG,
  1073. &dwDataReturn, sizeof(dwDataReturn));
  1074. //
  1075. // if the buffer size is too small here, throw everything
  1076. // away (including the NBT stuff) and return buffer size
  1077. // error. If all goes well the caller will call back shortly
  1078. // with a larger buffer and everything will be re-collected.
  1079. //
  1080. *lpcbTotalBytes = 0;
  1081. *lpNumObjectTypes = 0;
  1082. #ifndef USE_IPHLPAPI
  1083. SnmpUtilVarBindListFree (&IFVariableBindings);
  1084. SnmpUtilVarBindListFree (&VariableBindings);
  1085. SnmpUtilVarBindListFree (&VariableBindingsICMP);
  1086. #else
  1087. if (IfTable) {
  1088. RtlFreeHeap(RtlProcessHeap(), 0L, IfTable);
  1089. IfTable = NULL;
  1090. }
  1091. #endif
  1092. return ERROR_MORE_DATA;
  1093. }
  1094. if (bUseFriendlyNames) {
  1095. // replace any reserved characters in the instance name with safe ones
  1096. for (dwThisChar = 0; dwThisChar <= (InterfaceName.Length / sizeof (WCHAR)); dwThisChar++) {
  1097. switch (InterfaceName.Buffer[dwThisChar]) {
  1098. case L'(': InterfaceName.Buffer[dwThisChar] = L'['; break;
  1099. case L')': InterfaceName.Buffer[dwThisChar] = L']'; break;
  1100. case L'#': InterfaceName.Buffer[dwThisChar] = L'_'; break;
  1101. case L'/': InterfaceName.Buffer[dwThisChar] = L'_'; break;
  1102. case L'\\': InterfaceName.Buffer[dwThisChar] = L'_'; break;
  1103. default: break;
  1104. }
  1105. }
  1106. }
  1107. MonBuildInstanceDefinition (pPerfInstanceDefinition,
  1108. (PVOID *) &pPerfCounterBlock,
  1109. 0,
  1110. 0,
  1111. (bUseFriendlyNames ? (DWORD)PERF_NO_UNIQUE_ID : (DWORD)(Interface + 1)),
  1112. &InterfaceName);
  1113. if (bFreeName) {
  1114. RtlFreeUnicodeString(&InterfaceName);
  1115. }
  1116. pPerfCounterBlock->ByteLength = dwBlockSize;
  1117. pdwCounter = (PDWORD) (pPerfCounterBlock + 1);
  1118. #ifdef USE_IPHLPAPI
  1119. Assign64( IfTable->table[Interface].dwInOctets
  1120. + IfTable->table[Interface].dwOutOctets,
  1121. (PLARGE_INTEGER) pdwCounter);
  1122. REPORT_INFORMATION (TCP_COPYING_DATA, LOG_VERBOSE);
  1123. pdwPackets = pdwCounter + 2;
  1124. pdwCounter += 4; // skip packet counters first
  1125. *++pdwCounter = IfTable->table[Interface].dwSpeed;
  1126. *++pdwCounter = IfTable->table[Interface].dwInOctets;
  1127. ReceivedTemp = *++pdwCounter = IfTable->table[Interface].dwInUcastPkts;
  1128. ReceivedTemp += *++pdwCounter = IfTable->table[Interface].dwInNUcastPkts;
  1129. ReceivedTemp += *++pdwCounter = IfTable->table[Interface].dwInDiscards;
  1130. ReceivedTemp += *++pdwCounter = IfTable->table[Interface].dwInErrors;
  1131. ReceivedTemp += *++pdwCounter = IfTable->table[Interface].dwInUnknownProtos;
  1132. *++pdwCounter = IfTable->table[Interface].dwOutOctets;
  1133. SentTemp = *++pdwCounter = IfTable->table[Interface].dwOutUcastPkts;
  1134. SentTemp += *++pdwCounter = IfTable->table[Interface].dwOutNUcastPkts;
  1135. *++pdwCounter = IfTable->table[Interface].dwOutDiscards;
  1136. *++pdwCounter = IfTable->table[Interface].dwOutErrors;
  1137. *++pdwCounter = IfTable->table[Interface].dwOutQLen;
  1138. #else
  1139. Assign64( IF_COUNTER(IF_INOCTETS_INDEX) +
  1140. IF_COUNTER(IF_OUTOCTETS_INDEX,
  1141. (PLARGE_INTEGER) pdwCounter);
  1142. REPORT_INFORMATION (TCP_COPYING_DATA, LOG_VERBOSE);
  1143. pdwPackets = pdwCounter + 2;
  1144. pdwCounter += 4; // skip packet counters first
  1145. //
  1146. // NOTE: We are skipping 2 words for Total bytes,
  1147. // and one each for total packets, in packets & out packets
  1148. //
  1149. *++pdwCounter = IF_GAUGE(IF_SPEED_INDEX);
  1150. *++pdwCounter = IF_COUNTER(IF_INOCTETS_INDEX);
  1151. ReceivedTemp = *++pdwCounter = IF_COUNTER(IF_INUCASTPKTS_INDEX);
  1152. ReceivedTemp += *++pdwCounter = IF_COUNTER(IF_INNUCASTPKTS_INDEX);
  1153. ReceivedTemp += *++pdwCounter = IF_COUNTER(IF_INDISCARDS_INDEX);
  1154. ReceivedTemp += *++pdwCounter = IF_COUNTER(IF_INERRORS_INDEX);
  1155. ReceivedTemp += *++pdwCounter = IF_COUNTER(IF_INUNKNOWNPROTOS_INDEX);
  1156. *++pdwCounter = IF_COUNTER(IF_OUTOCTETS_INDEX);
  1157. SentTemp = *pdwCounter = IF_COUNTER(IF_OUTUCASTPKTS_INDEX);
  1158. SentTemp += *++pdwCounter = IF_COUNTER(IF_OUTNUCASTPKTS_INDEX);
  1159. *++pdwCounter = IF_COUNTER(IF_OUTDISCARDS_INDEX);
  1160. *++pdwCounter = IF_COUNTER(IF_OUTERRORS_INDEX);
  1161. *++pdwCounter = IF_COUNTER(IF_OUTQLEN_INDEX);
  1162. #endif
  1163. *pdwPackets = ReceivedTemp + SentTemp;
  1164. *++pdwPackets = ReceivedTemp;
  1165. *++pdwPackets = SentTemp;
  1166. pPerfInstanceDefinition = (PERF_INSTANCE_DEFINITION *)
  1167. (((PBYTE) pPerfCounterBlock) + dwBlockSize);
  1168. #ifndef USE_IPHLPAPI
  1169. #if USE_SNMP
  1170. // Prepare to get the data for the next network interface
  1171. if ( Interface < NetInterfaces ) {
  1172. for ( i = 0; i < NO_OF_IF_OIDS; i++ ) {
  1173. // SnmpUtilOidFree (&IFVariableBindingsArray[i].name);
  1174. SnmpUtilOidCpy (&IFVariableBindingsArray[i].name,
  1175. &IFVariableBindings.list[i].name);
  1176. }
  1177. }
  1178. SnmpUtilVarBindListFree (&IFVariableBindings);
  1179. IFVariableBindings.list = IFVariableBindingsArray;
  1180. IFVariableBindings.len = NO_OF_IF_OIDS;
  1181. #else
  1182. if ( Interface < NetInterfaces ) {
  1183. // since SnmpExtesionQuery returned newly allocated
  1184. // OID buffers, we need to:
  1185. // 1. free the original OID Buffers
  1186. // 2. copy the new into the old
  1187. // 3. free the returned buffers (OID's and data)
  1188. // 4. realloc a clean "new" buffer and
  1189. // 5. copy the new OIDS (with empty data) into
  1190. // new buffer
  1191. for ( i = 0; i < NO_OF_IF_OIDS; i++ ) {
  1192. // SnmpUtilOidFree (&IFVariableBindingsCall.list[i].name);
  1193. SnmpUtilOidCpy (&IFVariableBindingsCall.list[i].name,
  1194. &IFVariableBindings.list[i].name);
  1195. }
  1196. SnmpUtilVarBindListFree (&IFVariableBindings);
  1197. IFVariableBindings.list = RtlAllocateHeap (
  1198. RtlProcessHeap(),
  1199. 0L,
  1200. (RefIFVariableBindings.len * sizeof(RFC1157VarBind)));
  1201. if (!VariableBindings.list) {
  1202. REPORT_ERROR (TCP_SNMP_BUFFER_ALLOC_FAIL, LOG_DEBUG);
  1203. *lppData = lpDataTemp;
  1204. *lpcbTotalBytes = SpaceNeeded;
  1205. *lpNumObjectTypes = NumObjectTypesTemp;
  1206. #ifdef USE_IPHLPAPI
  1207. if (IfTable) {
  1208. RtlFreeHeap(RtlProcessHeap(), 0L, IfTable);
  1209. IfTable = NULL;
  1210. }
  1211. #endif
  1212. return ERROR_SUCCESS;
  1213. } else {
  1214. RtlMoveMemory (
  1215. IFVariableBindings.list,
  1216. IFVariableBindingsCall.list,
  1217. (IFVariableBindingsCall.len * sizeof(RFC1157VarBind)));
  1218. IFVariableBindings.len = RefIFVariableBindings.len;
  1219. }
  1220. }
  1221. #endif
  1222. #endif
  1223. HEAP_PROBE();
  1224. }
  1225. pNetInterfaceDataDefinition->NetInterfaceObjectType.TotalByteLength =
  1226. (DWORD)((PBYTE) pPerfInstanceDefinition - (PBYTE) pNetInterfaceDataDefinition);
  1227. pNetInterfaceDataDefinition->NetInterfaceObjectType.NumInstances =
  1228. NetInterfaces;
  1229. // setup counters and pointers for next counter
  1230. NumObjectTypesTemp += 1;
  1231. lpDataTemp = (LPVOID)pPerfInstanceDefinition;
  1232. // SpaceNeeded is kept up already
  1233. HEAP_PROBE();
  1234. if ( NetInterfaces ) {
  1235. #ifndef USE_IPHLPAPI
  1236. SnmpUtilVarBindListFree (&IFVariableBindings);
  1237. // SnmpUtilVarBindListFree (&IFVariableBindingsCall);
  1238. RtlFreeHeap (RtlProcessHeap(), 0L, IFVariableBindingsCall.list);
  1239. #endif
  1240. }
  1241. HEAP_PROBE();
  1242. } // end if Net Counters
  1243. // Get IP data
  1244. #ifdef USE_IPHLPAPI
  1245. if (IfTable) {
  1246. RtlFreeHeap(RtlProcessHeap(), 0L, IfTable);
  1247. IfTable = NULL;
  1248. }
  1249. #endif
  1250. HEAP_PROBE();
  1251. if (DO_COUNTER_OBJECT (dwCounterFlags, IP_OBJECT)) {
  1252. SpaceNeeded += (sizeof(IP_DATA_DEFINITION) + SIZE_OF_IP_DATA);
  1253. if ( *lpcbTotalBytes < SpaceNeeded ) {
  1254. dwDataReturn[0] = *lpcbTotalBytes;
  1255. dwDataReturn[1] = SpaceNeeded;
  1256. REPORT_WARNING_DATA (TCP_NET_IF_BUFFER_SIZE, LOG_DEBUG,
  1257. &dwDataReturn, sizeof(dwDataReturn));
  1258. //
  1259. // if the buffer size is too small here, throw everything
  1260. // away (including the NBT stuff) and return buffer size
  1261. // error. If all goes well the caller will call back shortly
  1262. // with a larger buffer and everything will be re-collected.
  1263. //
  1264. *lpcbTotalBytes = 0;
  1265. *lpNumObjectTypes = 0;
  1266. #ifndef USE_IPHLPAPI
  1267. SnmpUtilVarBindListFree (&VariableBindings);
  1268. SnmpUtilVarBindListFree (&VariableBindingsICMP);
  1269. #endif
  1270. return ERROR_MORE_DATA;
  1271. }
  1272. pIpDataDefinition = (IP_DATA_DEFINITION *) lpDataTemp;
  1273. RtlMoveMemory (pIpDataDefinition,
  1274. &IpDataDefinition,
  1275. sizeof (IP_DATA_DEFINITION));
  1276. pPerfCounterBlock = (PERF_COUNTER_BLOCK *) (pIpDataDefinition + 1);
  1277. pPerfCounterBlock->ByteLength = SIZE_OF_IP_DATA;
  1278. pdwCounter = (PDWORD) (pPerfCounterBlock + 1);
  1279. #ifdef USE_IPHLPAPI
  1280. *pdwCounter = IpStats.dwInReceives + IpStats.dwOutRequests;
  1281. *++pdwCounter = IpStats.dwInReceives;
  1282. *++pdwCounter = IpStats.dwInHdrErrors;
  1283. *++pdwCounter = IpStats.dwInAddrErrors;
  1284. *++pdwCounter = IpStats.dwForwDatagrams;
  1285. *++pdwCounter = IpStats.dwInUnknownProtos;
  1286. *++pdwCounter = IpStats.dwInDiscards;
  1287. *++pdwCounter = IpStats.dwInDelivers;
  1288. *++pdwCounter = IpStats.dwOutRequests;
  1289. *++pdwCounter = IpStats.dwOutDiscards;
  1290. *++pdwCounter = IpStats.dwOutNoRoutes;
  1291. *++pdwCounter = IpStats.dwReasmReqds;
  1292. *++pdwCounter = IpStats.dwReasmOks;
  1293. *++pdwCounter = IpStats.dwReasmFails;
  1294. *++pdwCounter = IpStats.dwFragOks;
  1295. *++pdwCounter = IpStats.dwFragFails;
  1296. *++pdwCounter = IpStats.dwFragCreates;
  1297. #else
  1298. *pdwCounter = IP_COUNTER(IP_INRECEIVES_INDEX) +
  1299. IP_COUNTER(IP_OUTREQUESTS_INDEX);
  1300. *++pdwCounter = IP_COUNTER(IP_INRECEIVES_INDEX);
  1301. *++pdwCounter = IP_COUNTER(IP_INHDRERRORS_INDEX);
  1302. *++pdwCounter = IP_COUNTER(IP_INADDRERRORS_INDEX);
  1303. *++pdwCounter = IP_COUNTER(IP_FORWDATAGRAMS_INDEX);
  1304. *++pdwCounter = IP_COUNTER(IP_INUNKNOWNPROTOS_INDEX);
  1305. *++pdwCounter = IP_COUNTER(IP_INDISCARDS_INDEX);
  1306. *++pdwCounter = IP_COUNTER(IP_INDELIVERS_INDEX);
  1307. *++pdwCounter = IP_COUNTER(IP_OUTREQUESTS_INDEX);
  1308. *++pdwCounter = IP_COUNTER(IP_OUTDISCARDS_INDEX);
  1309. *++pdwCounter = IP_COUNTER(IP_OUTNOROUTES_INDEX);
  1310. *++pdwCounter = IP_COUNTER(IP_REASMREQDS_INDEX);
  1311. *++pdwCounter = IP_COUNTER(IP_REASMOKS_INDEX);
  1312. *++pdwCounter = IP_COUNTER(IP_REASMFAILS_INDEX);
  1313. *++pdwCounter = IP_COUNTER(IP_FRAGOKS_INDEX);
  1314. *++pdwCounter = IP_COUNTER(IP_FRAGFAILS_INDEX);
  1315. *++pdwCounter = IP_COUNTER(IP_FRAGCREATES_INDEX);
  1316. #endif
  1317. // setup counters and pointers for next counter
  1318. NumObjectTypesTemp +=1;
  1319. lpDataTemp = (LPVOID)++pdwCounter;
  1320. // SpaceNeeded is kept up already
  1321. }
  1322. HEAP_PROBE();
  1323. // Get ICMP data
  1324. if (DO_COUNTER_OBJECT (dwCounterFlags, ICMP_OBJECT)) {
  1325. // The data for the network interfaces are now ready. So, let's get
  1326. // the data for the IP, ICMP, TCP and UDP protocols.
  1327. SpaceNeeded += (sizeof(ICMP_DATA_DEFINITION) + SIZE_OF_ICMP_DATA);
  1328. if ( *lpcbTotalBytes < SpaceNeeded ) {
  1329. dwDataReturn[0] = *lpcbTotalBytes;
  1330. dwDataReturn[1] = SpaceNeeded;
  1331. REPORT_WARNING_DATA (TCP_NET_IF_BUFFER_SIZE, LOG_DEBUG,
  1332. &dwDataReturn, sizeof(dwDataReturn));
  1333. //
  1334. // if the buffer size is too small here, throw everything
  1335. // away (including the NBT stuff) and return buffer size
  1336. // error. If all goes well the caller will call back shortly
  1337. // with a larger buffer and everything will be re-collected.
  1338. //
  1339. *lpcbTotalBytes = 0;
  1340. *lpNumObjectTypes = 0;
  1341. #ifndef USE_IPHLPAPI
  1342. SnmpUtilVarBindListFree (&VariableBindings);
  1343. SnmpUtilVarBindListFree (&VariableBindingsICMP);
  1344. #endif
  1345. return ERROR_MORE_DATA;
  1346. }
  1347. pIcmpDataDefinition = (ICMP_DATA_DEFINITION *) lpDataTemp;;
  1348. RtlMoveMemory (pIcmpDataDefinition,
  1349. &IcmpDataDefinition,
  1350. sizeof (ICMP_DATA_DEFINITION));
  1351. pPerfCounterBlock = (PERF_COUNTER_BLOCK *) (pIcmpDataDefinition + 1);
  1352. pPerfCounterBlock->ByteLength = SIZE_OF_ICMP_DATA;
  1353. pdwCounter = (PDWORD) (pPerfCounterBlock + 1);
  1354. #ifdef USE_IPHLPAPI
  1355. *pdwCounter = IcmpStats.stats.icmpInStats.dwMsgs
  1356. + IcmpStats.stats.icmpOutStats.dwMsgs;
  1357. *++pdwCounter = IcmpStats.stats.icmpInStats.dwMsgs;
  1358. *++pdwCounter = IcmpStats.stats.icmpInStats.dwErrors;
  1359. *++pdwCounter = IcmpStats.stats.icmpInStats.dwDestUnreachs;
  1360. *++pdwCounter = IcmpStats.stats.icmpInStats.dwTimeExcds;
  1361. *++pdwCounter = IcmpStats.stats.icmpInStats.dwParmProbs;
  1362. *++pdwCounter = IcmpStats.stats.icmpInStats.dwSrcQuenchs;
  1363. *++pdwCounter = IcmpStats.stats.icmpInStats.dwRedirects;
  1364. *++pdwCounter = IcmpStats.stats.icmpInStats.dwEchos;
  1365. *++pdwCounter = IcmpStats.stats.icmpInStats.dwEchoReps;
  1366. *++pdwCounter = IcmpStats.stats.icmpInStats.dwTimestamps;
  1367. *++pdwCounter = IcmpStats.stats.icmpInStats.dwTimestampReps;
  1368. *++pdwCounter = IcmpStats.stats.icmpInStats.dwAddrMasks;
  1369. *++pdwCounter = IcmpStats.stats.icmpInStats.dwAddrMaskReps;
  1370. *++pdwCounter = IcmpStats.stats.icmpOutStats.dwMsgs;
  1371. *++pdwCounter = IcmpStats.stats.icmpOutStats.dwErrors;
  1372. *++pdwCounter = IcmpStats.stats.icmpOutStats.dwDestUnreachs;
  1373. *++pdwCounter = IcmpStats.stats.icmpOutStats.dwTimeExcds;
  1374. *++pdwCounter = IcmpStats.stats.icmpOutStats.dwParmProbs;
  1375. *++pdwCounter = IcmpStats.stats.icmpOutStats.dwSrcQuenchs;
  1376. *++pdwCounter = IcmpStats.stats.icmpOutStats.dwRedirects;
  1377. *++pdwCounter = IcmpStats.stats.icmpOutStats.dwEchos;
  1378. *++pdwCounter = IcmpStats.stats.icmpOutStats.dwEchoReps;
  1379. *++pdwCounter = IcmpStats.stats.icmpOutStats.dwTimestamps;
  1380. *++pdwCounter = IcmpStats.stats.icmpOutStats.dwTimestampReps;
  1381. *++pdwCounter = IcmpStats.stats.icmpOutStats.dwAddrMasks;
  1382. *++pdwCounter = IcmpStats.stats.icmpOutStats.dwAddrMaskReps;
  1383. #else
  1384. *pdwCounter = ICMP_COUNTER(ICMP_INMSGS_INDEX) +
  1385. ICMP_COUNTER(ICMP_OUTMSGS_INDEX);
  1386. *++pdwCounter = ICMP_COUNTER(ICMP_INMSGS_INDEX);
  1387. *++pdwCounter = ICMP_COUNTER(ICMP_INERRORS_INDEX);
  1388. *++pdwCounter = ICMP_COUNTER(ICMP_INDESTUNREACHS_INDEX);
  1389. *++pdwCounter = ICMP_COUNTER(ICMP_INTIMEEXCDS_INDEX);
  1390. *++pdwCounter = ICMP_COUNTER(ICMP_INPARMPROBS_INDEX);
  1391. *++pdwCounter = ICMP_COUNTER(ICMP_INSRCQUENCHS_INDEX);
  1392. *++pdwCounter = ICMP_COUNTER(ICMP_INREDIRECTS_INDEX);
  1393. *++pdwCounter = ICMP_COUNTER(ICMP_INECHOS_INDEX);
  1394. *++pdwCounter = ICMP_COUNTER(ICMP_INECHOREPS_INDEX);
  1395. *++pdwCounter = ICMP_COUNTER(ICMP_INTIMESTAMPS_INDEX);
  1396. *++pdwCounter = ICMP_COUNTER(ICMP_INTIMESTAMPREPS_INDEX);
  1397. *++pdwCounter = ICMP_COUNTER(ICMP_INADDRMASKS_INDEX);
  1398. *++pdwCounter = ICMP_COUNTER(ICMP_INADDRMASKREPS_INDEX);
  1399. *++pdwCounter = ICMP_COUNTER(ICMP_OUTMSGS_INDEX);
  1400. *++pdwCounter = ICMP_COUNTER(ICMP_OUTERRORS_INDEX);
  1401. *++pdwCounter = ICMP_COUNTER(ICMP_OUTDESTUNREACHS_INDEX);
  1402. *++pdwCounter = ICMP_COUNTER(ICMP_OUTTIMEEXCDS_INDEX);
  1403. *++pdwCounter = ICMP_COUNTER(ICMP_OUTPARMPROBS_INDEX);
  1404. *++pdwCounter = ICMP_COUNTER(ICMP_OUTSRCQUENCHS_INDEX);
  1405. *++pdwCounter = ICMP_COUNTER(ICMP_OUTREDIRECTS_INDEX);
  1406. *++pdwCounter = ICMP_COUNTER(ICMP_OUTECHOS_INDEX);
  1407. *++pdwCounter = ICMP_COUNTER(ICMP_OUTECHOREPS_INDEX);
  1408. *++pdwCounter = ICMP_COUNTER(ICMP_OUTTIMESTAMPS_INDEX);
  1409. *++pdwCounter = ICMP_COUNTER(ICMP_OUTTIMESTAMPREPS_INDEX);
  1410. *++pdwCounter = ICMP_COUNTER(ICMP_OUTADDRMASKS_INDEX);
  1411. *++pdwCounter = ICMP_COUNTER(ICMP_OUTADDRMASKREPS_INDEX);
  1412. #endif
  1413. HEAP_PROBE();
  1414. // SnmpUtilVarBindListFree (&VariableBindingsICMP);
  1415. HEAP_PROBE();
  1416. // setup counters and pointers for next counter
  1417. NumObjectTypesTemp += 1;
  1418. lpDataTemp = (LPVOID)++pdwCounter;
  1419. // SpaceNeeded is kept up already
  1420. }
  1421. #ifndef USE_IPHLPAPI
  1422. SnmpUtilVarBindListFree (&VariableBindingsICMP);
  1423. #endif
  1424. HEAP_PROBE();
  1425. // Get TCP data
  1426. if (DO_COUNTER_OBJECT (dwCounterFlags, TCP_OBJECT)) {
  1427. // The data for the network interfaces are now ready. So, let's get
  1428. // the data for the IP, ICMP, TCP and UDP protocols.
  1429. SpaceNeeded += (sizeof(TCP_DATA_DEFINITION) + SIZE_OF_TCP_DATA);
  1430. if ( *lpcbTotalBytes < SpaceNeeded ) {
  1431. dwDataReturn[0] = *lpcbTotalBytes;
  1432. dwDataReturn[1] = SpaceNeeded;
  1433. REPORT_WARNING_DATA (TCP_NET_IF_BUFFER_SIZE, LOG_DEBUG,
  1434. &dwDataReturn, sizeof(dwDataReturn));
  1435. //
  1436. // if the buffer size is too small here, throw everything
  1437. // away (including the NBT stuff) and return buffer size
  1438. // error. If all goes well the caller will call back shortly
  1439. // with a larger buffer and everything will be re-collected.
  1440. //
  1441. *lpcbTotalBytes = 0;
  1442. *lpNumObjectTypes = 0;
  1443. #ifndef USE_IPHLPAPI
  1444. SnmpUtilVarBindListFree (&VariableBindings);
  1445. #endif
  1446. return ERROR_MORE_DATA;
  1447. }
  1448. pTcpDataDefinition = (TCP_DATA_DEFINITION *) lpDataTemp;
  1449. RtlMoveMemory (pTcpDataDefinition,
  1450. &TcpDataDefinition,
  1451. sizeof (TCP_DATA_DEFINITION));
  1452. pPerfCounterBlock = (PERF_COUNTER_BLOCK *) (pTcpDataDefinition + 1);
  1453. pPerfCounterBlock->ByteLength = SIZE_OF_TCP_DATA;
  1454. pdwCounter = (PDWORD) (pPerfCounterBlock + 1);
  1455. #ifdef USE_IPHLPAPI
  1456. *pdwCounter = TcpStats.dwInSegs + TcpStats.dwOutSegs;
  1457. *++pdwCounter = TcpStats.dwCurrEstab;
  1458. *++pdwCounter = TcpStats.dwActiveOpens;
  1459. *++pdwCounter = TcpStats.dwPassiveOpens;
  1460. *++pdwCounter = TcpStats.dwAttemptFails;
  1461. *++pdwCounter = TcpStats.dwEstabResets;
  1462. *++pdwCounter = TcpStats.dwInSegs;
  1463. *++pdwCounter = TcpStats.dwOutSegs;
  1464. *++pdwCounter = TcpStats.dwRetransSegs;
  1465. #else
  1466. *pdwCounter = TCP_COUNTER(TCP_INSEGS_INDEX) +
  1467. TCP_COUNTER(TCP_OUTSEGS_INDEX);
  1468. *++pdwCounter = TCP_GAUGE(TCP_CURRESTAB_INDEX);
  1469. *++pdwCounter = TCP_COUNTER(TCP_ACTIVEOPENS_INDEX);
  1470. *++pdwCounter = TCP_COUNTER(TCP_PASSIVEOPENS_INDEX);
  1471. *++pdwCounter = TCP_COUNTER(TCP_ATTEMPTFAILS_INDEX);
  1472. *++pdwCounter = TCP_COUNTER(TCP_ESTABRESETS_INDEX);
  1473. *++pdwCounter = TCP_COUNTER(TCP_INSEGS_INDEX);
  1474. *++pdwCounter = TCP_COUNTER(TCP_OUTSEGS_INDEX);
  1475. *++pdwCounter = TCP_COUNTER(TCP_RETRANSSEGS_INDEX);
  1476. #endif
  1477. // setup counters and pointers for next counter
  1478. NumObjectTypesTemp += 1;
  1479. lpDataTemp = (LPVOID)++pdwCounter;
  1480. // SpaceNeeded is kept up already
  1481. }
  1482. HEAP_PROBE();
  1483. // Get UDP data
  1484. if (DO_COUNTER_OBJECT (dwCounterFlags, UDP_OBJECT)) {
  1485. // The data for the network interfaces are now ready. So, let's get
  1486. // the data for the IP, ICMP, TCP and UDP protocols.
  1487. SpaceNeeded += (sizeof(UDP_DATA_DEFINITION) + SIZE_OF_UDP_DATA);
  1488. if ( *lpcbTotalBytes < SpaceNeeded ) {
  1489. dwDataReturn[0] = *lpcbTotalBytes;
  1490. dwDataReturn[1] = SpaceNeeded;
  1491. REPORT_WARNING_DATA (TCP_NET_IF_BUFFER_SIZE, LOG_DEBUG,
  1492. &dwDataReturn, sizeof(dwDataReturn));
  1493. //
  1494. // if the buffer size is too small here, throw everything
  1495. // away (including the NBT stuff) and return buffer size
  1496. // error. If all goes well the caller will call back shortly
  1497. // with a larger buffer and everything will be re-collected.
  1498. //
  1499. *lpcbTotalBytes = 0;
  1500. *lpNumObjectTypes = 0;
  1501. #ifndef USE_IPHLPAPI
  1502. SnmpUtilVarBindListFree (&VariableBindings);
  1503. #endif
  1504. return ERROR_MORE_DATA;
  1505. }
  1506. pUdpDataDefinition = (UDP_DATA_DEFINITION *) lpDataTemp;
  1507. RtlMoveMemory (pUdpDataDefinition,
  1508. &UdpDataDefinition,
  1509. sizeof (UDP_DATA_DEFINITION));
  1510. pPerfCounterBlock = (PERF_COUNTER_BLOCK *) (pUdpDataDefinition + 1);
  1511. pPerfCounterBlock->ByteLength = SIZE_OF_UDP_DATA;
  1512. pdwCounter = (PDWORD) (pPerfCounterBlock + 1);
  1513. #ifdef USE_IPHLPAPI
  1514. *pdwCounter = UdpStats.dwInDatagrams + UdpStats.dwOutDatagrams;
  1515. *++pdwCounter = UdpStats.dwInDatagrams;
  1516. *++pdwCounter = UdpStats.dwNoPorts;
  1517. *++pdwCounter = UdpStats.dwInErrors;
  1518. *++pdwCounter = UdpStats.dwOutDatagrams;
  1519. #else
  1520. *pdwCounter = UDP_COUNTER(UDP_INDATAGRAMS_INDEX) +
  1521. UDP_COUNTER(UDP_OUTDATAGRAMS_INDEX);
  1522. *++pdwCounter = UDP_COUNTER(UDP_INDATAGRAMS_INDEX);
  1523. *++pdwCounter = UDP_COUNTER(UDP_NOPORTS_INDEX);
  1524. *++pdwCounter = UDP_COUNTER(UDP_INERRORS_INDEX);
  1525. *++pdwCounter = UDP_COUNTER(UDP_OUTDATAGRAMS_INDEX);
  1526. #endif
  1527. // setup counters and pointers for next counter
  1528. NumObjectTypesTemp += 1;
  1529. lpDataTemp = (LPVOID)++pdwCounter;
  1530. // SpaceNeeded is kept up already
  1531. }
  1532. #ifndef USE_IPHLPAPI
  1533. #ifdef USE_SNMP
  1534. // Get prepared for the next data collection
  1535. VariableBindings.list = VariableBindingsArray + OIDS_OFFSET;
  1536. VariableBindings.len = OIDS_LENGTH;
  1537. VariableBindingsICMP.list = VariableBindingsArray + ICMP_OIDS_OFFSET;
  1538. VariableBindingsICMP.len = ICMP_OIDS_LENGTH;
  1539. #else
  1540. HEAP_PROBE();
  1541. SnmpUtilVarBindListFree (&VariableBindings);
  1542. HEAP_PROBE();
  1543. #endif
  1544. #endif
  1545. } // endif SNMP Objects
  1546. // Set the returned values
  1547. *lppData = ALIGN_ON_QWORD((LPVOID) lpDataTemp);
  1548. *lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
  1549. *lpNumObjectTypes = NumObjectTypesTemp;
  1550. HEAP_PROBE();
  1551. REPORT_SUCCESS (TCP_COLLECT_DATA, LOG_DEBUG);
  1552. return ERROR_SUCCESS;
  1553. } // CollectTcpIpPerformanceData
  1554. #pragma warning ( default : 4127)
  1555. DWORD
  1556. CloseTcpIpPerformanceData(
  1557. )
  1558. /*++
  1559. Routine Description:
  1560. This routine closes the open handles to TCP/IP devices.
  1561. Arguments:
  1562. None.
  1563. Return Value:
  1564. Win32 Status.
  1565. --*/
  1566. {
  1567. #ifndef USE_IPHLPAPI
  1568. int i;
  1569. #endif
  1570. REPORT_INFORMATION (TCP_ENTERING_CLOSE, LOG_VERBOSE);
  1571. if (dwTcpRefCount > 0) {
  1572. dwTcpRefCount--;
  1573. if (dwTcpRefCount == 0) {
  1574. // Close NBT
  1575. CloseNbtPerformanceData ();
  1576. #ifdef USE_DSIS
  1577. // Close DSIS
  1578. CloseDsisPerformanceData ();
  1579. #endif // USE_DSIS
  1580. /* This portion of the code for CloseTcpIpPerformanceData() could be used in
  1581. the CollectTcpIpPerformanceData() routine to close an open SNMP Manager
  1582. session.
  1583. So, name this portion of the code: B
  1584. */
  1585. #ifdef USE_SNMP
  1586. if ( TcpIpSession != (LPSNMP_MGR_SESSION) NULL ) {
  1587. if ( ! SnmpMgrClose (TcpIpSession) ) {
  1588. REPORT_ERROR_DATA (TCP_SNMP_MGR_CLOSE, LOG_DEBUG,
  1589. GetLastError (), sizeof(DWORD));
  1590. }
  1591. TcpIpSession = (LPSNMP_MGR_SESSION) NULL;
  1592. } else {
  1593. REPORT_WARNING (TCP_NULL_SESSION, LOG_DEBUG);
  1594. }
  1595. /* End of code B
  1596. */
  1597. #endif
  1598. HEAP_PROBE();
  1599. #ifndef USE_IPHLPAPI
  1600. for (i = 0; i < NO_OF_OIDS; i++) {
  1601. SnmpUtilOidFree ( &(RefNames[i]));
  1602. }
  1603. HEAP_PROBE();
  1604. for (i = 0; i < NO_OF_IF_OIDS; i++) {
  1605. SnmpUtilOidFree (&(IFPermVariableBindingsArray[i].name));
  1606. }
  1607. HEAP_PROBE();
  1608. #else
  1609. if (IfTable) {
  1610. RtlFreeHeap(RtlProcessHeap(), 0L, IfTable);
  1611. IfTable = NULL;
  1612. }
  1613. #endif
  1614. #if 0
  1615. // this is closed by the INETMIB1 on process detach
  1616. // so we don't need to do it here.
  1617. // close event handle used by SNMP
  1618. if (CloseHandle (hSnmpEvent)) {
  1619. hSnmpEvent = NULL;
  1620. }
  1621. #endif
  1622. #ifdef LOAD_INETMIB1
  1623. FreeLibrary (hInetMibDll);
  1624. #endif
  1625. }
  1626. }
  1627. MonCloseEventLog();
  1628. return ERROR_SUCCESS;
  1629. } // CloseTcpIpPerformanceData