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.

1473 lines
44 KiB

  1. /*++ BUILD Version: 0001 // Increment this if a change has global effects
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. perfnbf.c
  5. Abstract:
  6. This file implements the Extensible Objects for
  7. the Nbf LAN object types
  8. This code originally existed for NetBEUI only. Later, it was
  9. adaped to handle Netrware protocol level NWNB, SPX, and IPX.
  10. The code was not everywhere changed to reflect this, due to the
  11. lateness of the change. Therefore, sometimes you will see NBF
  12. where you should see TDI.
  13. Created:
  14. Russ Blake 07/30/92
  15. Revision History
  16. --*/
  17. //
  18. // Include Files
  19. //
  20. #include <nt.h>
  21. #include <ntrtl.h>
  22. #include <nturtl.h>
  23. #include <ntprfctr.h>
  24. #include <windows.h>
  25. #include <string.h>
  26. #include <stdlib.h>
  27. #include <nb30.h>
  28. #include <tdi.h>
  29. #include <winperf.h>
  30. #include "perfctr.h" // error message definition
  31. #include "perfmsg.h"
  32. #include "perfutil.h"
  33. #include "datanbf.h"
  34. //
  35. // References to constants which initialize the Object type definitions
  36. //
  37. extern NBF_DATA_DEFINITION NbfDataDefinition;
  38. extern NBF_RESOURCE_DATA_DEFINITION NbfResourceDataDefinition;
  39. //
  40. // TDI data structures
  41. //
  42. #define NBF_PROTOCOL 0
  43. #define IPX_PROTOCOL 1
  44. #define SPX_PROTOCOL 2
  45. #define NWNB_PROTOCOL 3
  46. #define NUMBER_OF_PROTOCOLS_HANDLED 4
  47. typedef struct _TDI_DATA_DEFINITION {
  48. int NumberOfResources;
  49. HANDLE fileHandle;
  50. UNICODE_STRING DeviceName;
  51. } TDI_DATA_DEFINITION, *PTDI_DATA_DEFINITION;
  52. typedef struct _TDI_PROTOCOLS_DATA {
  53. int NumOfDevices;
  54. int MaxDeviceName;
  55. int MaxNumOfResources;
  56. PTDI_DATA_DEFINITION pTDIData;
  57. } TDI_PROTOCOLS_DATA;
  58. TDI_PROTOCOLS_DATA TDITbl[NUMBER_OF_PROTOCOLS_HANDLED];
  59. DWORD dwTdiProtocolRefCount[NUMBER_OF_PROTOCOLS_HANDLED] = {0,0,0,0};
  60. DWORD dwTdiRefCount = 0;
  61. DWORD ObjectNameTitleIndices[NUMBER_OF_PROTOCOLS_HANDLED] = { 492,
  62. 488,
  63. 490,
  64. 398 };
  65. //
  66. // NBF data structures
  67. //
  68. ULONG ProviderStatsLength; // Resource-dependent size
  69. PTDI_PROVIDER_STATISTICS ProviderStats = NULL;
  70. // Provider statistics
  71. //
  72. // NetBUEI Resource Instance Names
  73. //
  74. LPCWSTR NetResourceName[] =
  75. {
  76. (LPCWSTR)L"Link(11)",
  77. (LPCWSTR)L"Address(12)",
  78. (LPCWSTR)L"Address File(13)",
  79. (LPCWSTR)L"Connection(14)",
  80. (LPCWSTR)L"Request(15)",
  81. (LPCWSTR)L"UI Frame(21)",
  82. (LPCWSTR)L"Packet(22)",
  83. (LPCWSTR)L"Receive Packet(23)",
  84. (LPCWSTR)L"Receive Buffer(24)"
  85. };
  86. #define NUMBER_OF_NAMES sizeof(NetResourceName)/sizeof(NetResourceName[0])
  87. #define MAX_NBF_RESOURCE_NAME_LENGTH 20
  88. //
  89. // Function Prototypes
  90. //
  91. PM_OPEN_PROC OpenNbfPerformanceData;
  92. PM_COLLECT_PROC CollectNbfPerformanceData;
  93. PM_CLOSE_PROC CloseNbfPerformanceData;
  94. PM_OPEN_PROC OpenIPXPerformanceData;
  95. PM_COLLECT_PROC CollectIPXPerformanceData;
  96. PM_CLOSE_PROC CloseIPXPerformanceData;
  97. PM_OPEN_PROC OpenSPXPerformanceData;
  98. PM_COLLECT_PROC CollectSPXPerformanceData;
  99. PM_CLOSE_PROC CloseSPXPerformanceData;
  100. PM_OPEN_PROC OpenNWNBPerformanceData;
  101. PM_COLLECT_PROC CollectNWNBPerformanceData;
  102. PM_CLOSE_PROC CloseNWNBPerformanceData;
  103. DWORD OpenTDIPerformanceData(LPWSTR lpDeviceNames,
  104. DWORD CurrentProtocol);
  105. DWORD CollectTDIPerformanceData(IN LPWSTR lpValueName,
  106. IN OUT LPVOID *lppData,
  107. IN OUT LPDWORD lpcbTotalBytes,
  108. IN OUT LPDWORD lpNumObjectTypes,
  109. IN DWORD CurrentProtocol);
  110. DWORD CloseTDIPerformanceData(DWORD CurrentProtocol);
  111. DWORD
  112. OpenNbfPerformanceData(
  113. LPWSTR lpDeviceNames
  114. )
  115. /*++
  116. Routine Description:
  117. This routine will open each device and remember the handle
  118. that the device returns.
  119. Arguments:
  120. Pointer to each device to be opened
  121. Return Value:
  122. None.
  123. --*/
  124. {
  125. return OpenTDIPerformanceData(lpDeviceNames, NBF_PROTOCOL);
  126. }
  127. DWORD
  128. OpenIPXPerformanceData(
  129. LPWSTR lpDeviceNames
  130. )
  131. /*++
  132. Routine Description:
  133. This routine will open each device and remember the handle
  134. that the device returns.
  135. Arguments:
  136. Pointer to each device to be opened
  137. Return Value:
  138. None.
  139. --*/
  140. {
  141. return OpenTDIPerformanceData(lpDeviceNames, IPX_PROTOCOL);
  142. }
  143. DWORD
  144. OpenSPXPerformanceData(
  145. LPWSTR lpDeviceNames
  146. )
  147. /*++
  148. Routine Description:
  149. This routine will open each device and remember the handle
  150. that the device returns.
  151. Arguments:
  152. Pointer to each device to be opened
  153. Return Value:
  154. None.
  155. --*/
  156. {
  157. DWORD dwStatus;
  158. dwStatus = OpenTDIPerformanceData(lpDeviceNames, SPX_PROTOCOL);
  159. if (dwStatus == ERROR_FILE_NOT_FOUND) {
  160. // no devices is not really an error, even though no counters
  161. // will be collected, this presents a much less alarming
  162. // message to the user.
  163. REPORT_WARNING (SPX_NO_DEVICE, LOG_USER);
  164. dwStatus = ERROR_SUCCESS;
  165. }
  166. return dwStatus;
  167. }
  168. DWORD
  169. OpenNWNBPerformanceData(
  170. LPWSTR lpDeviceNames
  171. )
  172. /*++
  173. Routine Description:
  174. This routine will open each device and remember the handle
  175. that the device returns.
  176. Arguments:
  177. Pointer to each device to be opened
  178. Return Value:
  179. None.
  180. --*/
  181. {
  182. return OpenTDIPerformanceData(lpDeviceNames, NWNB_PROTOCOL);
  183. }
  184. void
  185. CleanUpTDIData (
  186. DWORD CurrentProtocol
  187. )
  188. /*++
  189. Routine Description:
  190. This routine will celanup all the memory allocated for the
  191. CurrentProtocol
  192. Arguments:
  193. IN DWORD CurrentProtocol
  194. this is the index of the protocol for which we are currently
  195. gathering statistics
  196. Return Value:
  197. None.
  198. --*/
  199. {
  200. int NumOfDevices;
  201. int i;
  202. PTDI_DATA_DEFINITION pTDIData;
  203. pTDIData = TDITbl[CurrentProtocol].pTDIData;
  204. if (pTDIData == NULL)
  205. // nothing to cleanup
  206. return;
  207. NumOfDevices = TDITbl[CurrentProtocol].NumOfDevices;
  208. for (i=0; i < NumOfDevices; i++, pTDIData++) {
  209. if (pTDIData->DeviceName.Buffer) {
  210. RtlFreeHeap(RtlProcessHeap(), 0, pTDIData->DeviceName.Buffer);
  211. }
  212. if (pTDIData->fileHandle) {
  213. NtClose (pTDIData->fileHandle);
  214. }
  215. }
  216. RtlFreeHeap(RtlProcessHeap(), 0,
  217. TDITbl[CurrentProtocol].pTDIData);
  218. TDITbl[CurrentProtocol].pTDIData = NULL;
  219. }
  220. #pragma warning ( disable : 4127)
  221. DWORD
  222. OpenTDIPerformanceData(
  223. LPWSTR lpDeviceNames,
  224. DWORD CurrentProtocol
  225. )
  226. /*++
  227. Routine Description:
  228. This routine will open each device and remember the handle
  229. that the device returns.
  230. Arguments:
  231. IN LPWSTR lpDeviceNames
  232. pointer to each device to be opened
  233. IN DWORD CurrentProtocol
  234. this is the index of the protocol for which we are currently
  235. gathering statistics
  236. Return Value:
  237. None.
  238. --*/
  239. {
  240. NTSTATUS Status;
  241. UNICODE_STRING FileString;
  242. IO_STATUS_BLOCK IoStatusBlock;
  243. OBJECT_ATTRIBUTES ObjectAttributes;
  244. TDI_REQUEST_USER_QUERY_INFO QueryInfo;
  245. HANDLE fileHandle;
  246. LPWSTR lpLocalDeviceNames;
  247. int NumOfDevices;
  248. LPWSTR lpSaveDeviceName;
  249. PTDI_DATA_DEFINITION pTemp;
  250. PTDI_PROVIDER_INFO ProviderInfo=NULL;
  251. BOOL bInitThisProtocol = FALSE;
  252. MonOpenEventLog(); // this function maintains a reference count
  253. lpLocalDeviceNames = lpDeviceNames;
  254. if (dwTdiProtocolRefCount[CurrentProtocol] == 0) {
  255. bInitThisProtocol = TRUE;
  256. TDITbl[CurrentProtocol].MaxDeviceName = 0;
  257. NumOfDevices = TDITbl[CurrentProtocol].NumOfDevices = 0;
  258. TDITbl[CurrentProtocol].pTDIData = NULL;
  259. while (TRUE) {
  260. if (lpLocalDeviceNames == NULL || *lpLocalDeviceNames == L'\0') {
  261. break;
  262. }
  263. REPORT_INFORMATION_DATA (TDI_OPEN_ENTERED,
  264. LOG_VERBOSE,
  265. lpLocalDeviceNames,
  266. (lstrlenW(lpLocalDeviceNames) * sizeof(WCHAR)));
  267. RtlInitUnicodeString (&FileString, lpLocalDeviceNames);
  268. lpSaveDeviceName = RtlAllocateHeap(RtlProcessHeap(),
  269. HEAP_ZERO_MEMORY,
  270. sizeof (WCHAR) * (lstrlenW(lpLocalDeviceNames) + 1));
  271. if (!lpSaveDeviceName) {
  272. REPORT_ERROR (TDI_PROVIDER_STATS_MEMORY, LOG_USER);
  273. if (NumOfDevices == 0)
  274. return ERROR_OUTOFMEMORY;
  275. else
  276. break;
  277. }
  278. InitializeObjectAttributes(
  279. &ObjectAttributes,
  280. &FileString,
  281. OBJ_CASE_INSENSITIVE,
  282. NULL,
  283. NULL);
  284. Status = NtOpenFile(
  285. &fileHandle,
  286. SYNCHRONIZE | FILE_READ_DATA,
  287. &ObjectAttributes,
  288. &IoStatusBlock,
  289. FILE_SHARE_READ | FILE_SHARE_WRITE,
  290. FILE_SYNCHRONOUS_IO_ALERT);
  291. if (!NT_SUCCESS(Status)) {
  292. RtlFreeHeap(RtlProcessHeap(), 0, lpSaveDeviceName);
  293. REPORT_ERROR_DATA (TDI_OPEN_FILE_ERROR, LOG_DEBUG,
  294. lpLocalDeviceNames, (lstrlenW(lpLocalDeviceNames) * sizeof(WCHAR)));
  295. REPORT_ERROR_DATA (TDI_OPEN_FILE_ERROR, LOG_DEBUG,
  296. &IoStatusBlock, sizeof(IoStatusBlock));
  297. if (NumOfDevices == 0) {
  298. return RtlNtStatusToDosError(Status);
  299. } else {
  300. break;
  301. }
  302. }
  303. if (NumOfDevices == 0) {
  304. // allocate memory to hold the device data
  305. TDITbl[CurrentProtocol].pTDIData =
  306. RtlAllocateHeap(RtlProcessHeap(),
  307. HEAP_ZERO_MEMORY,
  308. sizeof(TDI_DATA_DEFINITION));
  309. if (TDITbl[CurrentProtocol].pTDIData == NULL) {
  310. REPORT_ERROR (TDI_PROVIDER_STATS_MEMORY, LOG_DEBUG);
  311. NtClose(fileHandle);
  312. RtlFreeHeap(RtlProcessHeap(), 0, lpSaveDeviceName);
  313. return ERROR_OUTOFMEMORY;
  314. }
  315. } else {
  316. // resize to hold multiple devices
  317. pTemp = RtlReAllocateHeap(RtlProcessHeap(), 0,
  318. TDITbl[CurrentProtocol].pTDIData,
  319. sizeof(TDI_DATA_DEFINITION) * (NumOfDevices + 1));
  320. if (pTemp == NULL) {
  321. NtClose(fileHandle);
  322. RtlFreeHeap(RtlProcessHeap(), 0, lpSaveDeviceName);
  323. CleanUpTDIData(CurrentProtocol);
  324. REPORT_ERROR (TDI_PROVIDER_STATS_MEMORY, LOG_USER);
  325. return ERROR_OUTOFMEMORY;
  326. } else {
  327. TDITbl[CurrentProtocol].pTDIData = pTemp;
  328. }
  329. }
  330. // build the TDI Data structure for this device instance
  331. TDITbl[CurrentProtocol].pTDIData[NumOfDevices].fileHandle
  332. = fileHandle;
  333. TDITbl[CurrentProtocol].pTDIData[NumOfDevices].DeviceName.MaximumLength =
  334. (WORD)(sizeof (WCHAR) * (lstrlenW(lpLocalDeviceNames) + 1));
  335. TDITbl[CurrentProtocol].pTDIData[NumOfDevices].DeviceName.Length =
  336. (WORD)(TDITbl[CurrentProtocol].pTDIData[NumOfDevices].DeviceName.Length - sizeof(WCHAR));
  337. TDITbl[CurrentProtocol].pTDIData[NumOfDevices].DeviceName.Buffer =
  338. lpSaveDeviceName;
  339. RtlCopyUnicodeString (
  340. &(TDITbl[CurrentProtocol].pTDIData[NumOfDevices].DeviceName),
  341. &FileString);
  342. if (TDITbl[CurrentProtocol].pTDIData[NumOfDevices].DeviceName.MaximumLength
  343. > TDITbl[CurrentProtocol].MaxDeviceName) {
  344. TDITbl[CurrentProtocol].MaxDeviceName =
  345. TDITbl[CurrentProtocol].pTDIData[NumOfDevices].DeviceName.MaximumLength;
  346. }
  347. // now increment NumOfDevices
  348. NumOfDevices++;
  349. TDITbl[CurrentProtocol].NumOfDevices = NumOfDevices;
  350. // increment to the next device string
  351. lpLocalDeviceNames += lstrlenW(lpLocalDeviceNames) + 1;
  352. }
  353. REPORT_INFORMATION (TDI_OPEN_FILE_SUCCESS, LOG_VERBOSE);
  354. }
  355. dwTdiProtocolRefCount[CurrentProtocol]++;
  356. if (TDITbl[CurrentProtocol].NumOfDevices == 0) {
  357. return ERROR_SUCCESS;
  358. }
  359. //
  360. // The following common buffer is used by all protocols. NBF
  361. // is bigger because of resource data returned.
  362. //
  363. if (ProviderStats == NULL && CurrentProtocol != NBF_PROTOCOL) {
  364. ProviderStatsLength = sizeof(TDI_PROVIDER_STATISTICS);
  365. ProviderStats = RtlAllocateHeap(RtlProcessHeap(),
  366. HEAP_ZERO_MEMORY,
  367. ProviderStatsLength);
  368. if (ProviderStats == NULL) {
  369. REPORT_ERROR (TDI_PROVIDER_STATS_MEMORY, LOG_USER);
  370. CleanUpTDIData(CurrentProtocol);
  371. return ERROR_OUTOFMEMORY;
  372. }
  373. }
  374. if ((CurrentProtocol == NBF_PROTOCOL) && bInitThisProtocol) {
  375. //
  376. // Query provider info to get resource count.
  377. //
  378. ProviderInfo = RtlAllocateHeap(RtlProcessHeap(),
  379. HEAP_ZERO_MEMORY,
  380. sizeof(TDI_PROVIDER_INFO));
  381. if ( ProviderInfo == NULL ) {
  382. REPORT_ERROR (TDI_PROVIDER_INFO_MEMORY, LOG_USER);
  383. CleanUpTDIData(CurrentProtocol);
  384. return ERROR_OUTOFMEMORY;
  385. }
  386. QueryInfo.QueryType = TDI_QUERY_PROVIDER_INFO;
  387. pTemp = TDITbl[CurrentProtocol].pTDIData;
  388. TDITbl[CurrentProtocol].MaxNumOfResources = 0;
  389. for (NumOfDevices = 0;
  390. NumOfDevices < TDITbl[CurrentProtocol].NumOfDevices;
  391. NumOfDevices++, pTemp++) {
  392. // loop thru all the devices to see if they can be opened
  393. // if one of them fails, then stop the whole thing.
  394. // we should probably save the good ones but...
  395. Status = NtDeviceIoControlFile(
  396. pTemp->fileHandle,
  397. NULL,
  398. NULL,
  399. NULL,
  400. &IoStatusBlock,
  401. IOCTL_TDI_QUERY_INFORMATION,
  402. (PVOID)&QueryInfo,
  403. sizeof(TDI_REQUEST_USER_QUERY_INFO),
  404. (PVOID)ProviderInfo,
  405. sizeof(TDI_PROVIDER_INFO));
  406. pTemp->NumberOfResources = ProviderInfo->NumberOfResources;
  407. if ((int)ProviderInfo->NumberOfResources >
  408. TDITbl[CurrentProtocol].MaxNumOfResources) {
  409. TDITbl[CurrentProtocol].MaxNumOfResources =
  410. ProviderInfo->NumberOfResources;
  411. }
  412. if (!NT_SUCCESS(Status)) {
  413. RtlFreeHeap(RtlProcessHeap(), 0, ProviderInfo);
  414. REPORT_ERROR (TDI_UNABLE_READ_DEVICE, LOG_DEBUG);
  415. REPORT_ERROR_DATA (TDI_IOCTL_FILE_ERROR, LOG_DEBUG,
  416. &IoStatusBlock, sizeof(IoStatusBlock));
  417. CleanUpTDIData(CurrentProtocol);
  418. return RtlNtStatusToDosError(Status);
  419. }
  420. }
  421. REPORT_INFORMATION (TDI_IOCTL_FILE, LOG_VERBOSE);
  422. ProviderStatsLength = sizeof(TDI_PROVIDER_STATISTICS) +
  423. (TDITbl[CurrentProtocol].MaxNumOfResources *
  424. sizeof(TDI_PROVIDER_RESOURCE_STATS));
  425. //
  426. // Buffer may have been allocated smaller by other protocol.
  427. //
  428. if (ProviderStats != NULL) {
  429. RtlFreeHeap(RtlProcessHeap(), 0, ProviderStats);
  430. }
  431. ProviderStats = RtlAllocateHeap(RtlProcessHeap(),
  432. HEAP_ZERO_MEMORY,
  433. ProviderStatsLength);
  434. if (ProviderStats == NULL) {
  435. REPORT_ERROR (TDI_PROVIDER_STATS_MEMORY, LOG_USER);
  436. RtlFreeHeap(RtlProcessHeap(), 0, ProviderInfo);
  437. CleanUpTDIData(CurrentProtocol);
  438. return ERROR_OUTOFMEMORY;
  439. }
  440. if (ProviderInfo) {
  441. RtlFreeHeap(RtlProcessHeap(), 0, ProviderInfo);
  442. }
  443. }
  444. dwTdiRefCount++;
  445. REPORT_INFORMATION (TDI_OPEN_PERFORMANCE_DATA, LOG_DEBUG);
  446. return ERROR_SUCCESS;
  447. }
  448. #pragma warning ( default : 4127)
  449. DWORD
  450. CollectNbfPerformanceData(
  451. IN LPWSTR lpValueName,
  452. IN OUT LPVOID *lppData,
  453. IN OUT LPDWORD lpcbTotalBytes,
  454. IN OUT LPDWORD lpNumObjectTypes
  455. )
  456. /*++
  457. Routine Description:
  458. This routine will return the data for the Nbf counters.
  459. Arguments:
  460. IN LPWSTR lpValueName
  461. pointer to a wide character string passed by registry.
  462. IN OUT LPVOID *lppData
  463. IN: pointer to the address of the buffer to receive the completed
  464. PerfDataBlock and subordinate structures. This routine will
  465. append its data to the buffer starting at the point referenced
  466. by *lppData.
  467. OUT: points to the first byte after the data structure added by this
  468. routine. This routine updated the value at lppdata after appending
  469. its data.
  470. IN OUT LPDWORD lpcbTotalBytes
  471. IN: the address of the DWORD that tells the size in bytes of the
  472. buffer referenced by the lppData argument
  473. OUT: the number of bytes added by this routine is writted to the
  474. DWORD pointed to by this argument
  475. IN OUT LPDWORD NumObjectTypes
  476. IN: the address of the DWORD to receive the number of objects added
  477. by this routine
  478. OUT: the number of objects added by this routine is writted to the
  479. DWORD pointed to by this argument
  480. Return Value:
  481. ERROR_MORE_DATA if buffer passed is too small to hold data
  482. any error conditions encountered are reported to the event log if
  483. event logging is enabled.
  484. ERROR_SUCCESS if success or any other error. Errors, however are
  485. also reported to the event log.
  486. --*/
  487. {
  488. return CollectTDIPerformanceData(lpValueName,
  489. lppData,
  490. lpcbTotalBytes,
  491. lpNumObjectTypes,
  492. NBF_PROTOCOL);
  493. }
  494. DWORD
  495. CollectIPXPerformanceData(
  496. IN LPWSTR lpValueName,
  497. IN OUT LPVOID *lppData,
  498. IN OUT LPDWORD lpcbTotalBytes,
  499. IN OUT LPDWORD lpNumObjectTypes
  500. )
  501. /*++
  502. Routine Description:
  503. This routine will return the data for the IPX counters.
  504. Arguments:
  505. IN LPWSTR lpValueName
  506. pointer to a wide character string passed by registry.
  507. IN OUT LPVOID *lppData
  508. IN: pointer to the address of the buffer to receive the completed
  509. PerfDataBlock and subordinate structures. This routine will
  510. append its data to the buffer starting at the point referenced
  511. by *lppData.
  512. OUT: points to the first byte after the data structure added by this
  513. routine. This routine updated the value at lppdata after appending
  514. its data.
  515. IN OUT LPDWORD lpcbTotalBytes
  516. IN: the address of the DWORD that tells the size in bytes of the
  517. buffer referenced by the lppData argument
  518. OUT: the number of bytes added by this routine is writted to the
  519. DWORD pointed to by this argument
  520. IN OUT LPDWORD NumObjectTypes
  521. IN: the address of the DWORD to receive the number of objects added
  522. by this routine
  523. OUT: the number of objects added by this routine is writted to the
  524. DWORD pointed to by this argument
  525. Return Value:
  526. ERROR_MORE_DATA if buffer passed is too small to hold data
  527. any error conditions encountered are reported to the event log if
  528. event logging is enabled.
  529. ERROR_SUCCESS if success or any other error. Errors, however are
  530. also reported to the event log.
  531. --*/
  532. {
  533. return CollectTDIPerformanceData(lpValueName,
  534. lppData,
  535. lpcbTotalBytes,
  536. lpNumObjectTypes,
  537. IPX_PROTOCOL);
  538. }
  539. DWORD
  540. CollectSPXPerformanceData(
  541. IN LPWSTR lpValueName,
  542. IN OUT LPVOID *lppData,
  543. IN OUT LPDWORD lpcbTotalBytes,
  544. IN OUT LPDWORD lpNumObjectTypes
  545. )
  546. /*++
  547. Routine Description:
  548. This routine will return the data for the SPX counters.
  549. Arguments:
  550. IN LPWSTR lpValueName
  551. pointer to a wide character string passed by registry.
  552. IN OUT LPVOID *lppData
  553. IN: pointer to the address of the buffer to receive the completed
  554. PerfDataBlock and subordinate structures. This routine will
  555. append its data to the buffer starting at the point referenced
  556. by *lppData.
  557. OUT: points to the first byte after the data structure added by this
  558. routine. This routine updated the value at lppdata after appending
  559. its data.
  560. IN OUT LPDWORD lpcbTotalBytes
  561. IN: the address of the DWORD that tells the size in bytes of the
  562. buffer referenced by the lppData argument
  563. OUT: the number of bytes added by this routine is writted to the
  564. DWORD pointed to by this argument
  565. IN OUT LPDWORD NumObjectTypes
  566. IN: the address of the DWORD to receive the number of objects added
  567. by this routine
  568. OUT: the number of objects added by this routine is writted to the
  569. DWORD pointed to by this argument
  570. Return Value:
  571. ERROR_MORE_DATA if buffer passed is too small to hold data
  572. any error conditions encountered are reported to the event log if
  573. event logging is enabled.
  574. ERROR_SUCCESS if success or any other error. Errors, however are
  575. also reported to the event log.
  576. --*/
  577. {
  578. return CollectTDIPerformanceData(lpValueName,
  579. lppData,
  580. lpcbTotalBytes,
  581. lpNumObjectTypes,
  582. SPX_PROTOCOL);
  583. }
  584. DWORD
  585. CollectNWNBPerformanceData(
  586. IN LPWSTR lpValueName,
  587. IN OUT LPVOID *lppData,
  588. IN OUT LPDWORD lpcbTotalBytes,
  589. IN OUT LPDWORD lpNumObjectTypes
  590. )
  591. /*++
  592. Routine Description:
  593. This routine will return the data for the NWNB counters.
  594. Arguments:
  595. IN LPWSTR lpValueName
  596. pointer to a wide character string passed by registry.
  597. IN OUT LPVOID *lppData
  598. IN: pointer to the address of the buffer to receive the completed
  599. PerfDataBlock and subordinate structures. This routine will
  600. append its data to the buffer starting at the point referenced
  601. by *lppData.
  602. OUT: points to the first byte after the data structure added by this
  603. routine. This routine updated the value at lppdata after appending
  604. its data.
  605. IN OUT LPDWORD lpcbTotalBytes
  606. IN: the address of the DWORD that tells the size in bytes of the
  607. buffer referenced by the lppData argument
  608. OUT: the number of bytes added by this routine is writted to the
  609. DWORD pointed to by this argument
  610. IN OUT LPDWORD NumObjectTypes
  611. IN: the address of the DWORD to receive the number of objects added
  612. by this routine
  613. OUT: the number of objects added by this routine is writted to the
  614. DWORD pointed to by this argument
  615. Return Value:
  616. ERROR_MORE_DATA if buffer passed is too small to hold data
  617. any error conditions encountered are reported to the event log if
  618. event logging is enabled.
  619. ERROR_SUCCESS if success or any other error. Errors, however are
  620. also reported to the event log.
  621. --*/
  622. {
  623. return CollectTDIPerformanceData(lpValueName,
  624. lppData,
  625. lpcbTotalBytes,
  626. lpNumObjectTypes,
  627. NWNB_PROTOCOL);
  628. }
  629. DWORD
  630. CollectTDIPerformanceData(
  631. IN LPWSTR lpValueName,
  632. IN OUT LPVOID *lppData,
  633. IN OUT LPDWORD lpcbTotalBytes,
  634. IN OUT LPDWORD lpNumObjectTypes,
  635. IN DWORD CurrentProtocol
  636. )
  637. /*++
  638. Routine Description:
  639. This routine will return the data for the TDI counters.
  640. Arguments:
  641. IN LPWSTR lpValueName
  642. pointer to a wide character string passed by registry.
  643. IN OUT LPVOID *lppData
  644. IN: pointer to the address of the buffer to receive the completed
  645. PerfDataBlock and subordinate structures. This routine will
  646. append its data to the buffer starting at the point referenced
  647. by *lppData.
  648. OUT: points to the first byte after the data structure added by this
  649. routine. This routine updated the value at lppdata after appending
  650. its data.
  651. IN OUT LPDWORD lpcbTotalBytes
  652. IN: the address of the DWORD that tells the size in bytes of the
  653. buffer referenced by the lppData argument
  654. OUT: the number of bytes added by this routine is writted to the
  655. DWORD pointed to by this argument
  656. IN OUT LPDWORD NumObjectTypes
  657. IN: the address of the DWORD to receive the number of objects added
  658. by this routine
  659. OUT: the number of objects added by this routine is writted to the
  660. DWORD pointed to by this argument
  661. IN DWORD CurrentProtocol
  662. this is the index of the protocol for which we are currently
  663. gathering statistics
  664. Return Value:
  665. ERROR_MORE_DATA if buffer passed is too small to hold data
  666. any error conditions encountered are reported to the event log if
  667. event logging is enabled.
  668. ERROR_SUCCESS if success or any other error. Errors, however are
  669. also reported to the event log.
  670. --*/
  671. {
  672. // Variables for reformating the data
  673. ULONG SpaceNeeded;
  674. PDWORD pdwCounter = NULL;
  675. LARGE_INTEGER UNALIGNED *pliCounter;
  676. LARGE_INTEGER UNALIGNED *pliFrameBytes;
  677. LARGE_INTEGER UNALIGNED *pliDatagramBytes;
  678. PERF_COUNTER_BLOCK *pPerfCounterBlock;
  679. NBF_DATA_DEFINITION *pNbfDataDefinition;
  680. NBF_RESOURCE_DATA_DEFINITION *pNbfResourceDataDefinition;
  681. // Variables for collecting the data from Nbf
  682. NTSTATUS Status;
  683. IO_STATUS_BLOCK IoStatusBlock;
  684. PERF_INSTANCE_DEFINITION *pPerfInstanceDefinition;
  685. TDI_REQUEST_USER_QUERY_INFO QueryInfo;
  686. // Variables for collecting data about Nbf Resouces
  687. int NumResource;
  688. ULONG ResourceSpace;
  689. UNICODE_STRING ResourceName;
  690. WCHAR ResourceNameBuffer[MAX_NBF_RESOURCE_NAME_LENGTH + 1];
  691. INT NumOfDevices;
  692. PTDI_DATA_DEFINITION pTDIData;
  693. INT i;
  694. INT TotalNumberOfResources;
  695. // variables used for error logging
  696. DWORD dwDataReturn[2];
  697. DWORD dwQueryType;
  698. if (lpValueName == NULL) {
  699. REPORT_INFORMATION (TDI_COLLECT_ENTERED, LOG_VERBOSE);
  700. } else {
  701. REPORT_INFORMATION_DATA (TDI_COLLECT_ENTERED,
  702. LOG_VERBOSE,
  703. lpValueName,
  704. (DWORD)(lstrlenW(lpValueName)*sizeof(WCHAR)));
  705. }
  706. //
  707. // before doing anything else,
  708. // see if this is a foreign (i.e. non-NT) computer data request
  709. //
  710. dwQueryType = GetQueryType (lpValueName);
  711. if ((dwQueryType == QUERY_COSTLY) || (dwQueryType == QUERY_FOREIGN)) {
  712. // NBF foriegn data requests are not supported so bail out
  713. REPORT_INFORMATION (TDI_FOREIGN_DATA_REQUEST, LOG_VERBOSE);
  714. *lpcbTotalBytes = (DWORD) 0;
  715. *lpNumObjectTypes = (DWORD) 0;
  716. return ERROR_SUCCESS;
  717. }
  718. if (dwQueryType == QUERY_ITEMS){
  719. if (CurrentProtocol == NBF_PROTOCOL) {
  720. if ( !(IsNumberInUnicodeList (ObjectNameTitleIndices[CurrentProtocol],
  721. lpValueName)) &&
  722. !(IsNumberInUnicodeList (NBF_RESOURCE_OBJECT_TITLE_INDEX,
  723. lpValueName))) {
  724. // request received for objects not provided by NBF
  725. REPORT_INFORMATION (TDI_UNSUPPORTED_ITEM_REQUEST, LOG_VERBOSE);
  726. *lpcbTotalBytes = (DWORD) 0;
  727. *lpNumObjectTypes = (DWORD) 0;
  728. return ERROR_SUCCESS;
  729. }
  730. } // NBF_PROTOCOL
  731. else if ( !(IsNumberInUnicodeList (ObjectNameTitleIndices[CurrentProtocol],
  732. lpValueName))) {
  733. // request received for objects not provided by this protocol
  734. REPORT_INFORMATION (TDI_UNSUPPORTED_ITEM_REQUEST, LOG_VERBOSE);
  735. *lpcbTotalBytes = (DWORD) 0;
  736. *lpNumObjectTypes = (DWORD) 0;
  737. return ERROR_SUCCESS;
  738. } // other protocol
  739. } // dwQueryType == QUERY_ITEMS
  740. // if no NBF devices were opened, in the OPEN routine, then
  741. // leave now.
  742. if (TDITbl[CurrentProtocol].pTDIData == NULL) {
  743. REPORT_WARNING (TDI_NULL_HANDLE, LOG_DEBUG);
  744. *lpcbTotalBytes = (DWORD) 0;
  745. *lpNumObjectTypes = (DWORD) 0;
  746. return ERROR_SUCCESS;
  747. }
  748. pNbfDataDefinition = (NBF_DATA_DEFINITION *) *lppData;
  749. pTDIData = TDITbl[CurrentProtocol].pTDIData;
  750. NumOfDevices = TDITbl[CurrentProtocol].NumOfDevices;
  751. // Compute space needed to hold Nbf Resource Data
  752. if (CurrentProtocol != NBF_PROTOCOL) {
  753. ResourceSpace = 0;
  754. } else {
  755. ResourceSpace = sizeof(NBF_RESOURCE_DATA_DEFINITION) +
  756. (TDITbl[CurrentProtocol].MaxNumOfResources *
  757. (sizeof(PERF_INSTANCE_DEFINITION) +
  758. QWORD_MULTIPLE(
  759. (MAX_NBF_RESOURCE_NAME_LENGTH * sizeof(WCHAR)) +
  760. sizeof(UNICODE_NULL)) +
  761. SIZE_OF_NBF_RESOURCE_DATA));
  762. ResourceSpace *= NumOfDevices;
  763. }
  764. SpaceNeeded = sizeof(NBF_DATA_DEFINITION) +
  765. SIZE_OF_NBF_DATA +
  766. ResourceSpace;
  767. // now add in the per instance NBF data
  768. SpaceNeeded += NumOfDevices *
  769. (SIZE_OF_NBF_DATA +
  770. sizeof(PERF_INSTANCE_DEFINITION) +
  771. QWORD_MULTIPLE(
  772. (TDITbl[CurrentProtocol].MaxDeviceName * sizeof(WCHAR))
  773. + sizeof(UNICODE_NULL)));
  774. if ( *lpcbTotalBytes < SpaceNeeded ) {
  775. dwDataReturn[0] = *lpcbTotalBytes;
  776. dwDataReturn[1] = SpaceNeeded;
  777. REPORT_WARNING_DATA (TDI_DATA_BUFFER_SIZE_ERROR,
  778. LOG_DEBUG,
  779. &dwDataReturn,
  780. sizeof(dwDataReturn));
  781. *lpcbTotalBytes = (DWORD) 0;
  782. *lpNumObjectTypes = (DWORD) 0;
  783. return ERROR_MORE_DATA;
  784. }
  785. REPORT_INFORMATION (TDI_DATA_BUFFER_SIZE_SUCCESS, LOG_VERBOSE);
  786. //
  787. // Copy the (constant, initialized) Object Type and counter definitions
  788. //
  789. RtlMoveMemory(pNbfDataDefinition,
  790. &NbfDataDefinition,
  791. sizeof(NBF_DATA_DEFINITION));
  792. pNbfDataDefinition->NbfObjectType.ObjectNameTitleIndex =
  793. ObjectNameTitleIndices[CurrentProtocol];
  794. pNbfDataDefinition->NbfObjectType.ObjectHelpTitleIndex =
  795. ObjectNameTitleIndices[CurrentProtocol] + 1;
  796. pPerfInstanceDefinition = (PERF_INSTANCE_DEFINITION *)
  797. &pNbfDataDefinition[1];
  798. if (NumOfDevices > 0) {
  799. for (i=0; i < NumOfDevices; i++, pTDIData++) {
  800. //
  801. // Format and collect Nbf data
  802. //
  803. QueryInfo.QueryType = TDI_QUERY_PROVIDER_STATISTICS;
  804. Status = NtDeviceIoControlFile(
  805. pTDIData->fileHandle,
  806. NULL,
  807. NULL,
  808. NULL,
  809. &IoStatusBlock,
  810. IOCTL_TDI_QUERY_INFORMATION,
  811. (PVOID)&QueryInfo,
  812. sizeof(TDI_REQUEST_USER_QUERY_INFO),
  813. (PVOID)ProviderStats,
  814. ProviderStatsLength);
  815. if (Status != STATUS_SUCCESS) {
  816. REPORT_ERROR (TDI_UNABLE_READ_DEVICE, LOG_DEBUG);
  817. REPORT_ERROR_DATA (TDI_QUERY_INFO_ERROR,
  818. LOG_DEBUG,
  819. &IoStatusBlock,
  820. sizeof (IoStatusBlock));
  821. *lpcbTotalBytes = (DWORD) 0;
  822. *lpNumObjectTypes = (DWORD) 0;
  823. return ERROR_SUCCESS;
  824. }
  825. REPORT_INFORMATION (TDI_QUERY_INFO_SUCCESS, LOG_DEBUG);
  826. MonBuildInstanceDefinition(
  827. pPerfInstanceDefinition,
  828. (PVOID *)&pPerfCounterBlock,
  829. 0,
  830. 0,
  831. (DWORD)PERF_NO_UNIQUE_ID,
  832. &(pTDIData->DeviceName));
  833. pPerfCounterBlock->ByteLength = SIZE_OF_NBF_DATA;
  834. pdwCounter = (PDWORD) (&pPerfCounterBlock[1]);
  835. *pdwCounter = ProviderStats->DatagramsSent +
  836. ProviderStats->DatagramsReceived;
  837. pliCounter = (LARGE_INTEGER UNALIGNED *) ++pdwCounter;
  838. pliDatagramBytes = pliCounter;
  839. pliCounter->QuadPart = ProviderStats->DatagramBytesSent.QuadPart +
  840. ProviderStats->DatagramBytesReceived.QuadPart;
  841. pdwCounter = (PDWORD) ++pliCounter;
  842. *pdwCounter = ProviderStats->PacketsSent + ProviderStats->PacketsReceived;
  843. *++pdwCounter = ProviderStats->DataFramesSent +
  844. ProviderStats->DataFramesReceived;
  845. pliCounter = (LARGE_INTEGER UNALIGNED *) ++pdwCounter;
  846. pliFrameBytes = pliCounter;
  847. pliCounter->QuadPart = ProviderStats->DataFrameBytesSent.QuadPart +
  848. ProviderStats->DataFrameBytesReceived.QuadPart;
  849. // Get the Bytes Total/sec which is the sum of Frame Byte /sec
  850. // and Datagram byte/sec
  851. ++pliCounter;
  852. pliCounter->QuadPart = pliDatagramBytes->QuadPart +
  853. pliFrameBytes->QuadPart;
  854. //
  855. // Get the TDI raw data.
  856. //
  857. pdwCounter = (PDWORD) ++pliCounter;
  858. *pdwCounter = ProviderStats->OpenConnections;
  859. *++pdwCounter = ProviderStats->ConnectionsAfterNoRetry;
  860. *++pdwCounter = ProviderStats->ConnectionsAfterRetry;
  861. *++pdwCounter = ProviderStats->LocalDisconnects;
  862. *++pdwCounter = ProviderStats->RemoteDisconnects;
  863. *++pdwCounter = ProviderStats->LinkFailures;
  864. *++pdwCounter = ProviderStats->AdapterFailures;
  865. *++pdwCounter = ProviderStats->SessionTimeouts;
  866. *++pdwCounter = ProviderStats->CancelledConnections;
  867. *++pdwCounter = ProviderStats->RemoteResourceFailures;
  868. *++pdwCounter = ProviderStats->LocalResourceFailures;
  869. *++pdwCounter = ProviderStats->NotFoundFailures;
  870. *++pdwCounter = ProviderStats->NoListenFailures;
  871. *++pdwCounter = ProviderStats->DatagramsSent;
  872. pliCounter = (LARGE_INTEGER UNALIGNED *) ++pdwCounter;
  873. *pliCounter = ProviderStats->DatagramBytesSent;
  874. pdwCounter = (PDWORD) ++pliCounter;
  875. *pdwCounter = ProviderStats->DatagramsReceived;
  876. pliCounter = (LARGE_INTEGER UNALIGNED *) ++pdwCounter;
  877. *pliCounter = ProviderStats->DatagramBytesReceived;
  878. pdwCounter = (PDWORD) ++pliCounter;
  879. *pdwCounter = ProviderStats->PacketsSent;
  880. *++pdwCounter = ProviderStats->PacketsReceived;
  881. *++pdwCounter = ProviderStats->DataFramesSent;
  882. pliCounter = (LARGE_INTEGER UNALIGNED *) ++pdwCounter;
  883. *pliCounter = ProviderStats->DataFrameBytesSent;
  884. pdwCounter = (PDWORD) ++pliCounter;
  885. *pdwCounter = ProviderStats->DataFramesReceived;
  886. pliCounter = (LARGE_INTEGER UNALIGNED *) ++pdwCounter;
  887. *pliCounter = ProviderStats->DataFrameBytesReceived;
  888. pdwCounter = (PDWORD) ++pliCounter;
  889. *pdwCounter = ProviderStats->DataFramesResent;
  890. pliCounter = (LARGE_INTEGER UNALIGNED *) ++pdwCounter;
  891. *pliCounter = ProviderStats->DataFrameBytesResent;
  892. pdwCounter = (PDWORD) ++pliCounter;
  893. *pdwCounter = ProviderStats->DataFramesRejected;
  894. pliCounter = (LARGE_INTEGER UNALIGNED *) ++pdwCounter;
  895. *pliCounter = ProviderStats->DataFrameBytesRejected;
  896. pdwCounter = (PDWORD) ++pliCounter;
  897. *pdwCounter = ProviderStats->ResponseTimerExpirations;
  898. *++pdwCounter = ProviderStats->AckTimerExpirations;
  899. *++pdwCounter = ProviderStats->MaximumSendWindow;
  900. *++pdwCounter = ProviderStats->AverageSendWindow;
  901. *++pdwCounter = ProviderStats->PiggybackAckQueued;
  902. *++pdwCounter = ProviderStats->PiggybackAckTimeouts;
  903. *++pdwCounter = 0; //reserved
  904. pPerfInstanceDefinition = (PERF_INSTANCE_DEFINITION *)
  905. ((PBYTE) pPerfCounterBlock +
  906. SIZE_OF_NBF_DATA);
  907. }
  908. pNbfResourceDataDefinition = (NBF_RESOURCE_DATA_DEFINITION *)
  909. ++pdwCounter;
  910. } else {
  911. pNbfResourceDataDefinition = (NBF_RESOURCE_DATA_DEFINITION *)
  912. pPerfInstanceDefinition;
  913. }
  914. TotalNumberOfResources = 0;
  915. pNbfDataDefinition->NbfObjectType.NumInstances = NumOfDevices;
  916. pNbfDataDefinition->NbfObjectType.TotalByteLength =
  917. (DWORD)((PBYTE) pdwCounter - (PBYTE) pNbfDataDefinition);
  918. if (CurrentProtocol == NBF_PROTOCOL) {
  919. RtlMoveMemory(pNbfResourceDataDefinition,
  920. &NbfResourceDataDefinition,
  921. sizeof(NBF_RESOURCE_DATA_DEFINITION));
  922. pPerfInstanceDefinition = (PERF_INSTANCE_DEFINITION *)
  923. &pNbfResourceDataDefinition[1];
  924. pTDIData = TDITbl[CurrentProtocol].pTDIData;
  925. for (i = 0; i < NumOfDevices; i++, pTDIData++) {
  926. // for most cases, we will have only one deivce,
  927. // then we could just use the ProviderStats read
  928. // for NBF data.
  929. if (NumOfDevices > 1) {
  930. // need to read ProviderStat again for multiple devices
  931. QueryInfo.QueryType = TDI_QUERY_PROVIDER_STATISTICS;
  932. Status = NtDeviceIoControlFile(
  933. pTDIData->fileHandle,
  934. NULL,
  935. NULL,
  936. NULL,
  937. &IoStatusBlock,
  938. IOCTL_TDI_QUERY_INFORMATION,
  939. (PVOID)&QueryInfo,
  940. sizeof(TDI_REQUEST_USER_QUERY_INFO),
  941. (PVOID)ProviderStats,
  942. ProviderStatsLength);
  943. if (Status != STATUS_SUCCESS) {
  944. REPORT_ERROR (TDI_UNABLE_READ_DEVICE, LOG_DEBUG);
  945. REPORT_ERROR_DATA (TDI_QUERY_INFO_ERROR,
  946. LOG_DEBUG,
  947. &IoStatusBlock,
  948. sizeof (IoStatusBlock));
  949. *lpcbTotalBytes = (DWORD) 0;
  950. *lpNumObjectTypes = (DWORD) 0;
  951. return ERROR_SUCCESS;
  952. }
  953. }
  954. TotalNumberOfResources += pTDIData->NumberOfResources;
  955. for ( NumResource = 0;
  956. NumResource < pTDIData->NumberOfResources;
  957. NumResource++ ) {
  958. //
  959. // Format and collect Nbf Resource data
  960. //
  961. if (NumResource < NUMBER_OF_NAMES) {
  962. RtlInitUnicodeString(&ResourceName,
  963. NetResourceName[NumResource]);
  964. } else {
  965. ResourceName.Length = 0;
  966. ResourceName.MaximumLength = MAX_NBF_RESOURCE_NAME_LENGTH +
  967. sizeof(UNICODE_NULL);
  968. ResourceName.Buffer = ResourceNameBuffer;
  969. RtlIntegerToUnicodeString(NumResource,
  970. 10,
  971. &ResourceName);
  972. }
  973. MonBuildInstanceDefinition(
  974. pPerfInstanceDefinition,
  975. (PVOID *)&pPerfCounterBlock,
  976. ObjectNameTitleIndices[CurrentProtocol],
  977. i,
  978. (DWORD)PERF_NO_UNIQUE_ID,
  979. &ResourceName);
  980. pPerfCounterBlock->ByteLength = SIZE_OF_NBF_RESOURCE_DATA;
  981. pdwCounter = (PDWORD)&pPerfCounterBlock[1]; // define pointer to first
  982. // counter in block
  983. *pdwCounter++ =
  984. ProviderStats->ResourceStats[NumResource].MaximumResourceUsed;
  985. *pdwCounter++ =
  986. ProviderStats->ResourceStats[NumResource].AverageResourceUsed;
  987. *pdwCounter++ =
  988. ProviderStats->ResourceStats[NumResource].ResourceExhausted;
  989. // set pointer to where next instance buffer should show up
  990. pPerfInstanceDefinition = (PERF_INSTANCE_DEFINITION *)
  991. ((PBYTE) pPerfCounterBlock +
  992. SIZE_OF_NBF_RESOURCE_DATA);
  993. // set for loop termination
  994. pdwCounter = (PDWORD) pPerfInstanceDefinition;
  995. } // NumberOfResources
  996. } // NumOfDevices
  997. } // NBF_PROTOCOL
  998. *lppData = pdwCounter;
  999. pNbfResourceDataDefinition->NbfResourceObjectType.TotalByteLength =
  1000. (DWORD)((PBYTE) pdwCounter - (PBYTE) pNbfResourceDataDefinition);
  1001. if (CurrentProtocol != NBF_PROTOCOL) {
  1002. *lpNumObjectTypes = 1;
  1003. // bytes used are those of the first (i.e. only) object returned
  1004. *lpcbTotalBytes = pNbfDataDefinition->NbfObjectType.TotalByteLength;
  1005. } else {
  1006. // set count of object types returned
  1007. *lpNumObjectTypes = NBF_NUM_PERF_OBJECT_TYPES;
  1008. // set length of this object
  1009. *lpcbTotalBytes;
  1010. // note the bytes used by first object
  1011. *lpcbTotalBytes = pNbfDataDefinition->NbfObjectType.TotalByteLength;
  1012. // add the bytes used by the second object
  1013. *lpcbTotalBytes +=
  1014. pNbfResourceDataDefinition->NbfResourceObjectType.TotalByteLength;
  1015. // set number of instances loaded
  1016. pNbfResourceDataDefinition->NbfResourceObjectType.NumInstances =
  1017. TotalNumberOfResources;
  1018. }
  1019. REPORT_INFORMATION (TDI_COLLECT_DATA, LOG_DEBUG);
  1020. return ERROR_SUCCESS;
  1021. }
  1022. DWORD
  1023. CloseNbfPerformanceData(
  1024. )
  1025. /*++
  1026. Routine Description:
  1027. This routine closes the open handles to Nbf devices.
  1028. Arguments:
  1029. None.
  1030. Return Value:
  1031. ERROR_SUCCESS
  1032. --*/
  1033. {
  1034. return CloseTDIPerformanceData(NBF_PROTOCOL);
  1035. }
  1036. DWORD
  1037. CloseIPXPerformanceData(
  1038. )
  1039. /*++
  1040. Routine Description:
  1041. This routine closes the open handles to IPX devices.
  1042. Arguments:
  1043. None.
  1044. Return Value:
  1045. ERROR_SUCCESS
  1046. --*/
  1047. {
  1048. return CloseTDIPerformanceData(IPX_PROTOCOL);
  1049. }
  1050. DWORD
  1051. CloseSPXPerformanceData(
  1052. )
  1053. /*++
  1054. Routine Description:
  1055. This routine closes the open handles to SPX devices.
  1056. Arguments:
  1057. None.
  1058. Return Value:
  1059. ERROR_SUCCESS
  1060. --*/
  1061. {
  1062. return CloseTDIPerformanceData(SPX_PROTOCOL);
  1063. }
  1064. DWORD
  1065. CloseNWNBPerformanceData(
  1066. )
  1067. /*++
  1068. Routine Description:
  1069. This routine closes the open handles to NWNB devices.
  1070. Arguments:
  1071. None.
  1072. Return Value:
  1073. ERROR_SUCCESS
  1074. --*/
  1075. {
  1076. return CloseTDIPerformanceData(NWNB_PROTOCOL);
  1077. }
  1078. DWORD
  1079. CloseTDIPerformanceData(
  1080. DWORD CurrentProtocol
  1081. )
  1082. /*++
  1083. Routine Description:
  1084. This routine closes the open handles to TDI devices.
  1085. Arguments:
  1086. Current protocol index.
  1087. Return Value:
  1088. ERROR_SUCCESS
  1089. --*/
  1090. {
  1091. REPORT_INFORMATION (TDI_CLOSE_ENTERED, LOG_VERBOSE);
  1092. if (dwTdiProtocolRefCount[CurrentProtocol] > 0) {
  1093. dwTdiProtocolRefCount[CurrentProtocol]--;
  1094. if (dwTdiProtocolRefCount[CurrentProtocol] == 0) {
  1095. CleanUpTDIData (CurrentProtocol);
  1096. }
  1097. }
  1098. if (dwTdiRefCount > 0) {
  1099. dwTdiRefCount--;
  1100. if (dwTdiRefCount == 0) {
  1101. if ( ProviderStats ) {
  1102. RtlFreeHeap(RtlProcessHeap(), 0, ProviderStats);
  1103. ProviderStats = NULL;
  1104. REPORT_INFORMATION (TDI_PROVIDER_STATS_FREED, LOG_VERBOSE);
  1105. }
  1106. }
  1107. }
  1108. MonCloseEventLog ();
  1109. return ERROR_SUCCESS;
  1110. }