Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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