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.

925 lines
26 KiB

  1. /*++ BUILD Version: 0002 // Increment this if a change has global effects
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. perfnbt.c
  5. Abstract:
  6. This file implements the Extensible Objects for
  7. the LAN object types
  8. Created:
  9. Revision History:
  10. --*/
  11. //
  12. // include files
  13. //
  14. #include <nt.h>
  15. #include <ntrtl.h>
  16. #include <nturtl.h>
  17. #include <ntstatus.h>
  18. #include <windows.h>
  19. #include <fcntl.h>
  20. #include <string.h>
  21. #include <stdlib.h>
  22. #include <stdio.h>
  23. #include <winperf.h>
  24. #include "perfctr.h" // error message definition
  25. #include "perfmsg.h"
  26. #include "perfutil.h"
  27. #include "perfnbt.h"
  28. #include "datanbt.h"
  29. // New header file for getting nbt data
  30. #pragma warning (disable : 4201)
  31. #include <tdi.h>
  32. #include <nbtioctl.h>
  33. #pragma warning (default : 4201)
  34. enum eSTATE
  35. {
  36. NBT_RECONNECTING, // waiting for the worker thread to run NbtConnect
  37. NBT_IDLE, // not Transport connection
  38. NBT_ASSOCIATED, // associated with an address element
  39. NBT_CONNECTING, // establishing Transport connection
  40. NBT_SESSION_INBOUND, // waiting for a session request after tcp connection setup inbound
  41. NBT_SESSION_WAITACCEPT, // waiting for accept after a listen has been satisfied
  42. NBT_SESSION_OUTBOUND, // waiting for a session response after tcp connection setup
  43. NBT_SESSION_UP, // got positive response
  44. NBT_DISCONNECTING, // sent a disconnect down to Tcp, but it hasn't completed yet
  45. NBT_DISCONNECTED // a session has been disconnected but not closed with TCP yet
  46. };
  47. //
  48. // References to constants which initialize the Object type definitions
  49. //
  50. extern NBT_DATA_DEFINITION NbtDataDefinition;
  51. #define NBT_CONNECTION_NAME_LENGTH 17
  52. #define NETBIOS_NAME_SIZE NBT_CONNECTION_NAME_LENGTH-1
  53. //
  54. // Nbt data structures
  55. //
  56. typedef struct _NBT_DEVICE_DATA {
  57. HANDLE hFileHandle;
  58. UNICODE_STRING DeviceName;
  59. } NBT_DEVICE_DATA, *PNBT_DEVICE_DATA;
  60. PNBT_DEVICE_DATA pNbtDeviceData;
  61. int MaxNbtDeviceName;
  62. int NumberOfNbtDevices;
  63. // initial count - will update to last
  64. PVOID pNbtDataBuffer = NULL;
  65. int NbtDataBufferSize;
  66. DWORD dwNbtRefCount = 0;
  67. // HANDLE NbtHandle = INVALID_HANDLE_VALUE; // Handle of Nbt Device
  68. #define NBT_CONTROLLING_STREAM "CSB" // Ignore Controlling Stream XEB
  69. #define NBT_LISTEN_CONNECTION 3 // All NBT connections with type <= 3,
  70. // are just listening for clients
  71. // The error value returned by the perfctrs.dll when an error occurs while we
  72. // are getting the data for the NBT connections.
  73. // The error codes we get from the socket calls (OpenStream(), s_ioctl(),
  74. // getmsg()) are Unix errors, not Dos or Windows errors. Hopefully, somebody
  75. // will implement the conversion from these errors to Windows errors.
  76. // The error value is not used within the Collect data routine because this
  77. // routine shouldn't return an error in case it fails to collect Nbt data from
  78. // connections. In this case, it just returns the buffer it was supposed to
  79. // place the data into, unchanged.
  80. #define ERROR_NBT_NET_RESPONSE \
  81. (RtlNtStatusToDosError(STATUS_INVALID_NETWORK_RESPONSE))
  82. #define BUFF_SIZE 650
  83. PM_OPEN_PROC OpenNbtPerformanceData;
  84. PM_COLLECT_PROC CollectNbtPerformanceData;
  85. PM_CLOSE_PROC CloseNbtPerformanceData;
  86. //------------------------------------------------------------------------
  87. NTSTATUS
  88. OpenNbt(
  89. IN char *path,
  90. OUT PHANDLE pHandle,
  91. OUT UNICODE_STRING *uc_name_string
  92. )
  93. /*++
  94. Routine Description:
  95. This function opens a stream.
  96. Arguments:
  97. path - path to the STREAMS driver
  98. oflag - currently ignored. In the future, O_NONBLOCK will be
  99. relevant.
  100. ignored - not used
  101. Return Value:
  102. An NT handle for the stream, or INVALID_HANDLE_VALUE if unsuccessful.
  103. --*/
  104. {
  105. HANDLE StreamHandle;
  106. OBJECT_ATTRIBUTES ObjectAttributes;
  107. IO_STATUS_BLOCK IoStatusBlock;
  108. STRING name_string;
  109. // UNICODE_STRING uc_name_string;
  110. NTSTATUS status;
  111. RtlInitString(&name_string, path);
  112. RtlAnsiStringToUnicodeString(uc_name_string, &name_string, TRUE);
  113. InitializeObjectAttributes(
  114. &ObjectAttributes,
  115. uc_name_string,
  116. OBJ_CASE_INSENSITIVE,
  117. (HANDLE) NULL,
  118. (PSECURITY_DESCRIPTOR) NULL
  119. );
  120. status =
  121. NtCreateFile(
  122. &StreamHandle,
  123. SYNCHRONIZE | FILE_READ_DATA ,
  124. // SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
  125. &ObjectAttributes,
  126. &IoStatusBlock,
  127. NULL,
  128. FILE_ATTRIBUTE_NORMAL,
  129. FILE_SHARE_READ | FILE_SHARE_WRITE,
  130. FILE_OPEN_IF,
  131. 0,
  132. NULL,
  133. 0);
  134. // RtlFreeUnicodeString(&uc_name_string);
  135. *pHandle = StreamHandle;
  136. return(status);
  137. } // Open_nbt
  138. NTSTATUS
  139. DeviceIoCtrl(
  140. IN HANDLE fd,
  141. IN PVOID ReturnBuffer,
  142. IN ULONG BufferSize,
  143. IN ULONG Ioctl
  144. )
  145. /*++
  146. Routine Description:
  147. This procedure performs an ioctl(I_STR) on a stream.
  148. Arguments:
  149. fd - NT file handle
  150. iocp - pointer to a strioctl structure
  151. Return Value:
  152. 0 if successful, -1 otherwise.
  153. --*/
  154. {
  155. NTSTATUS status;
  156. TDI_REQUEST_QUERY_INFORMATION QueryInfo;
  157. IO_STATUS_BLOCK iosb;
  158. PVOID pInput;
  159. ULONG SizeInput;
  160. if (Ioctl == IOCTL_TDI_QUERY_INFORMATION)
  161. {
  162. pInput = &QueryInfo;
  163. QueryInfo.QueryType = TDI_QUERY_ADAPTER_STATUS; // node status or whatever
  164. SizeInput = sizeof(TDI_REQUEST_QUERY_INFORMATION);
  165. }
  166. else
  167. {
  168. pInput = NULL;
  169. SizeInput = 0;
  170. }
  171. status = NtDeviceIoControlFile(
  172. fd, // Handle
  173. NULL, // Event
  174. NULL, // ApcRoutine
  175. NULL, // ApcContext
  176. &iosb, // IoStatusBlock
  177. Ioctl, // IoControlCode
  178. pInput, // InputBuffer
  179. SizeInput, // InputBufferSize
  180. (PVOID) ReturnBuffer, // OutputBuffer
  181. BufferSize); // OutputBufferSize
  182. if (status == STATUS_PENDING)
  183. {
  184. status = NtWaitForSingleObject(
  185. fd, // Handle
  186. TRUE, // Alertable
  187. NULL); // Timeout
  188. }
  189. return(status);
  190. } // DeviceIoCtrl
  191. PCHAR
  192. printable(
  193. IN PCHAR string,
  194. IN PCHAR StrOut
  195. )
  196. /*++
  197. Routine Description:
  198. This procedure converts non prinatble characaters to periods ('.')
  199. Arguments:
  200. string - the string to convert
  201. StrOut - ptr to a string to put the converted string into
  202. Return Value:
  203. a ptr to the string that was converted (Strout)
  204. --*/
  205. {
  206. PCHAR Out;
  207. PCHAR cp;
  208. LONG i;
  209. Out = StrOut;
  210. for (cp = string, i= 0; i < NETBIOS_NAME_SIZE; cp++,i++) {
  211. if (isprint(*cp)) {
  212. *Out++ = *cp;
  213. continue;
  214. }
  215. if (*cp >= 128) { /* extended characters are ok */
  216. *Out++ = *cp;
  217. continue;
  218. }
  219. *Out++ = '.';
  220. }
  221. return(StrOut);
  222. } // printable
  223. #pragma warning ( disable : 4127)
  224. DWORD
  225. OpenNbtPerformanceData (
  226. IN LPWSTR dwVoid // not used by this routine
  227. )
  228. /*++
  229. Routine Description:
  230. This routine will open the Nbt device and remember the handle returned
  231. by the device.
  232. Arguments:
  233. None.
  234. Return Value:
  235. ERROR_NBT_NET_RESPONSE if unable to open NBT stream device
  236. ERROR_SUCCESS if open was successful
  237. --*/
  238. {
  239. PCHAR SubKeyLinkage=(PCHAR)"system\\currentcontrolset\\services\\netbt\\linkage";
  240. PCHAR Linkage=(PCHAR)"Export";
  241. CHAR *pBuffer = NULL;
  242. CHAR *lpLocalDeviceNames;
  243. LONG status, status2;
  244. DWORD Type;
  245. ULONG size;
  246. HKEY Key;
  247. HANDLE hFileHandle;
  248. UNICODE_STRING fileString;
  249. NTSTATUS ntstatus;
  250. PNBT_DEVICE_DATA pTemp;
  251. UNREFERENCED_PARAMETER (dwVoid);
  252. MonOpenEventLog();
  253. REPORT_INFORMATION (NBT_OPEN_ENTERED, LOG_VERBOSE);
  254. if (InterlockedIncrement(&dwNbtRefCount) == 1) {
  255. status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  256. SubKeyLinkage,
  257. 0,
  258. KEY_READ,
  259. &Key);
  260. if (status == ERROR_SUCCESS) {
  261. // now read the linkage values
  262. size = 0;
  263. pBuffer = NULL;
  264. status2 = RegQueryValueEx(Key,
  265. Linkage,
  266. NULL,
  267. &Type,
  268. (LPBYTE)pBuffer,
  269. &size);
  270. if ((size > 0) &&
  271. ((status2 == ERROR_MORE_DATA) ||
  272. (status2 == ERROR_SUCCESS))) {
  273. pBuffer = RtlAllocateHeap(
  274. RtlProcessHeap(), 0, size);
  275. if (pBuffer == NULL) {
  276. RegCloseKey(Key);
  277. return ERROR_OUTOFMEMORY;
  278. }
  279. status2 = RegQueryValueEx(Key,
  280. Linkage,
  281. NULL,
  282. &Type,
  283. (LPBYTE)pBuffer,
  284. &size);
  285. }
  286. RegCloseKey(Key);
  287. if (status2 != ERROR_SUCCESS) {
  288. if (pBuffer != NULL) {
  289. RtlFreeHeap(RtlProcessHeap(), 0, pBuffer);
  290. }
  291. return ERROR_SUCCESS;
  292. }
  293. }
  294. else {
  295. return ERROR_SUCCESS;
  296. }
  297. if (pBuffer == NULL) {
  298. return ERROR_SUCCESS;
  299. }
  300. lpLocalDeviceNames = pBuffer;
  301. while (TRUE) {
  302. if (*lpLocalDeviceNames == '\0') {
  303. break;
  304. }
  305. ntstatus = OpenNbt (lpLocalDeviceNames,
  306. &hFileHandle,
  307. &fileString);
  308. if (ntstatus == ERROR_SUCCESS) {
  309. if (NumberOfNbtDevices == 0) {
  310. // allocate memory to hold the device data
  311. pNbtDeviceData = RtlAllocateHeap(RtlProcessHeap(),
  312. HEAP_ZERO_MEMORY,
  313. sizeof(NBT_DEVICE_DATA));
  314. if (pNbtDeviceData == NULL) {
  315. RtlFreeUnicodeString(&fileString);
  316. if (pBuffer) {
  317. RtlFreeHeap(RtlProcessHeap(), 0, pBuffer);
  318. }
  319. return ERROR_OUTOFMEMORY;
  320. }
  321. }
  322. else {
  323. // resize to hold multiple devices
  324. pTemp = RtlReAllocateHeap(RtlProcessHeap(), 0,
  325. pNbtDeviceData,
  326. sizeof(NBT_DEVICE_DATA) * (NumberOfNbtDevices + 1));
  327. if (pTemp == NULL) {
  328. NtClose(hFileHandle);
  329. RtlFreeUnicodeString(&fileString);
  330. RtlFreeHeap(RtlProcessHeap(), 0, pNbtDeviceData);
  331. pNbtDeviceData = NULL;
  332. REPORT_ERROR (TDI_PROVIDER_STATS_MEMORY, LOG_USER);
  333. break;
  334. }
  335. else {
  336. pNbtDeviceData = pTemp;
  337. }
  338. }
  339. // build the Data structure for this device instance
  340. pNbtDeviceData[NumberOfNbtDevices].hFileHandle
  341. = hFileHandle;
  342. pNbtDeviceData[NumberOfNbtDevices].DeviceName.MaximumLength =
  343. fileString.MaximumLength;
  344. pNbtDeviceData[NumberOfNbtDevices].DeviceName.Length =
  345. fileString.Length;
  346. pNbtDeviceData[NumberOfNbtDevices].DeviceName.Buffer =
  347. fileString.Buffer;
  348. NumberOfNbtDevices++;
  349. if (fileString.MaximumLength > MaxNbtDeviceName) {
  350. MaxNbtDeviceName = fileString.MaximumLength;
  351. }
  352. } // ntstatus OK
  353. else {
  354. RtlFreeUnicodeString(&fileString);
  355. }
  356. // increment to the next device string
  357. // lpLocalDeviceNames += strlen(lpLocalDeviceNames) + 1;
  358. // we only support one device at this point since we cannot
  359. // tell which Connection goes with which device
  360. break;
  361. } // while TRUE
  362. }
  363. REPORT_SUCCESS (NBT_OPEN_PERFORMANCE_DATA, LOG_DEBUG);
  364. if (pBuffer) {
  365. RtlFreeHeap(RtlProcessHeap(), 0, pBuffer);
  366. }
  367. return ERROR_SUCCESS;
  368. }
  369. #pragma warning ( default : 4127)
  370. DWORD
  371. CollectNbtPerformanceData(
  372. IN LPWSTR lpValueName,
  373. IN OUT LPVOID *lppData,
  374. IN OUT LPDWORD lpcbTotalBytes,
  375. IN OUT LPDWORD lpNumObjectTypes
  376. )
  377. /*++
  378. Routine Description:
  379. This routine will return the data for the Nbt counters.
  380. IN LPWSTR lpValueName
  381. pointer to a wide character null-terminated string passed by the
  382. registry.
  383. IN OUT LPVOID *lppData
  384. IN: pointer to the address of the buffer to receive the completed
  385. PerfDataBlock and subordinate structures. This routine will
  386. append its data to the buffer starting at the point referenced
  387. by *lppData.
  388. OUT: points to the first byte after the data structure added by this
  389. routine. This routine updated the value at lppdata after appending
  390. its data.
  391. IN OUT LPDWORD lpcbTotalBytes
  392. IN: the address of the DWORD that tells the size in bytes of the
  393. buffer referenced by the lppData argument
  394. OUT: the number of bytes added by this routine is writted to the
  395. DWORD pointed to by this argument
  396. IN OUT LPDWORD lpNumObjectTypes
  397. IN: the address of the DWORD to receive the number of objects added
  398. by this routine
  399. OUT: the number of objects added by this routine is writted to the
  400. DWORD pointed to by this argument
  401. Return Value:
  402. ERROR_MORE_DATA if buffer passed is too small to hold data
  403. any error conditions encountered are reported to the event log if
  404. event logging is enabled.
  405. ERROR_SUCCESS if success or any other error. Errors, however are
  406. also reported to the event log.
  407. --*/
  408. {
  409. // Variables for reformatting the Nbt data
  410. LARGE_INTEGER UNALIGNED *pliCounter;
  411. NBT_DATA_DEFINITION *pNbtDataDefinition;
  412. PPERF_OBJECT_TYPE pNbtObject;
  413. ULONG SpaceNeeded;
  414. UNICODE_STRING ConnectionName;
  415. ANSI_STRING AnsiConnectionName;
  416. WCHAR ConnectionNameBuffer[NBT_CONNECTION_NAME_LENGTH + 20];
  417. #if 0
  418. // be sure to check the reference below...
  419. WCHAR DeviceNameBuffer[NBT_CONNECTION_NAME_LENGTH + 1 + 128];
  420. #endif
  421. CHAR AnsiConnectionNameBuffer[NBT_CONNECTION_NAME_LENGTH + 1 + 20];
  422. WCHAR TotalName[] = L"Total";
  423. PERF_INSTANCE_DEFINITION *pPerfInstanceDefinition;
  424. PERF_COUNTER_BLOCK *pPerfCounterBlock;
  425. CHAR NameOut[NETBIOS_NAME_SIZE +4];
  426. // int ConnectionCounter = 0; /* this is not used anymore */
  427. LARGE_INTEGER TotalReceived, TotalSent;
  428. DWORD dwDataReturn[2];
  429. NTSTATUS status;
  430. tCONNECTION_LIST *pConList;
  431. tCONNECTIONS *pConns;
  432. LONG Count;
  433. int i;
  434. int NumberOfConnections = 5; // assume 5 to start
  435. PVOID pOldBuffer;
  436. if (lpValueName == NULL) {
  437. REPORT_INFORMATION (NBT_COLLECT_ENTERED, LOG_VERBOSE);
  438. } else {
  439. REPORT_INFORMATION_DATA (NBT_COLLECT_ENTERED, LOG_VERBOSE,
  440. lpValueName, (lstrlenW(lpValueName) * sizeof(WCHAR)));
  441. }
  442. //
  443. // define pointer for Object Data structure (NBT object def.)
  444. //
  445. pNbtDataDefinition = (NBT_DATA_DEFINITION *) *lppData;
  446. pNbtObject = (PPERF_OBJECT_TYPE) pNbtDataDefinition;
  447. if (!pNbtDeviceData || NumberOfNbtDevices == 0)
  448. {
  449. //
  450. // Error getting NBT info, so return 0 bytes, 0 objects and
  451. // log error
  452. //
  453. if (NumberOfNbtDevices > 0) {
  454. // only report an error if there are devices
  455. // returning data but they can't be read.
  456. REPORT_ERROR (NBT_IOCTL_INFO_ERROR, LOG_USER);
  457. }
  458. *lpcbTotalBytes = (DWORD) 0;
  459. *lpNumObjectTypes = (DWORD) 0;
  460. return ERROR_SUCCESS;
  461. }
  462. if (!pNbtDataBuffer)
  463. {
  464. NbtDataBufferSize = 1024L;
  465. pNbtDataBuffer = RtlAllocateHeap(RtlProcessHeap(),
  466. HEAP_ZERO_MEMORY,
  467. NbtDataBufferSize
  468. );
  469. if (!pNbtDataBuffer)
  470. {
  471. *lpcbTotalBytes = (DWORD) 0;
  472. *lpNumObjectTypes = (DWORD) 0;
  473. return ERROR_SUCCESS;
  474. }
  475. }
  476. REPORT_SUCCESS (NBT_IOCTL_INFO_SUCCESS, LOG_VERBOSE);
  477. // Compute space needed to hold NBT data
  478. SpaceNeeded = sizeof(NBT_DATA_DEFINITION) +
  479. (NumberOfConnections *
  480. NumberOfNbtDevices *
  481. (sizeof(PERF_INSTANCE_DEFINITION) +
  482. QWORD_MULTIPLE((NBT_CONNECTION_NAME_LENGTH + 1) * sizeof(WCHAR)) +
  483. QWORD_MULTIPLE(MaxNbtDeviceName)
  484. + SIZE_OF_NBT_DATA));
  485. if ( *lpcbTotalBytes < SpaceNeeded ) {
  486. dwDataReturn[0] = *lpcbTotalBytes;
  487. dwDataReturn[1] = SpaceNeeded;
  488. REPORT_WARNING_DATA (NBT_DATA_BUFFER_SIZE, LOG_DEBUG,
  489. &dwDataReturn, sizeof (dwDataReturn));
  490. return ERROR_MORE_DATA;
  491. }
  492. AnsiConnectionName.Length =
  493. AnsiConnectionName.MaximumLength = sizeof(AnsiConnectionNameBuffer);
  494. AnsiConnectionName.Buffer = AnsiConnectionNameBuffer;
  495. //
  496. // If here, then there's a object to display so initialize
  497. // the Object data structure in the buffer passed to us.
  498. //
  499. RtlMoveMemory(pNbtDataDefinition, &NbtDataDefinition, sizeof(NBT_DATA_DEFINITION));
  500. //
  501. // point to where the first instance of this will be (if we find one.
  502. //
  503. pPerfInstanceDefinition = (PERF_INSTANCE_DEFINITION *)
  504. (pNbtDataDefinition + 1);
  505. TotalReceived.LowPart = 0; // initialize counters
  506. TotalSent.LowPart = 0;
  507. TotalReceived.HighPart = 0; // initialize counters
  508. TotalSent.HighPart = 0;
  509. // NOTE:- we only support NumberOfNbtDevices == 1 since
  510. // DeviceIoCtrl can't tell which connection is for which NBT device
  511. for (i=0; i < NumberOfNbtDevices; i++)
  512. {
  513. if (pNbtDeviceData[i].hFileHandle == 0 ||
  514. pNbtDeviceData[i].hFileHandle == INVALID_HANDLE_VALUE)
  515. {
  516. continue;
  517. }
  518. status = STATUS_BUFFER_OVERFLOW;
  519. while (status == STATUS_BUFFER_OVERFLOW)
  520. {
  521. status = DeviceIoCtrl (
  522. pNbtDeviceData[i].hFileHandle,
  523. pNbtDataBuffer,
  524. NbtDataBufferSize,
  525. IOCTL_NETBT_GET_CONNECTIONS);
  526. if (status == STATUS_BUFFER_OVERFLOW)
  527. {
  528. // resize to hold multiple devices
  529. NbtDataBufferSize += 1024L;
  530. pOldBuffer = pNbtDataBuffer;
  531. pNbtDataBuffer = RtlReAllocateHeap(RtlProcessHeap(), 0,
  532. pNbtDataBuffer,
  533. NbtDataBufferSize);
  534. if (pNbtDataBuffer == NULL || NbtDataBufferSize == 0x0FFFFL)
  535. {
  536. *lpcbTotalBytes = (DWORD) 0;
  537. *lpNumObjectTypes = (DWORD) 0;
  538. RtlFreeHeap(RtlProcessHeap(), 0, pOldBuffer);
  539. pNbtDataBuffer = NULL;
  540. return ERROR_SUCCESS;
  541. }
  542. }
  543. } // while Buffer overflow
  544. pConList = (tCONNECTION_LIST *) pNbtDataBuffer;
  545. Count = pConList->ConnectionCount;
  546. pConns = pConList->ConnList;
  547. if (Count == 0)
  548. {
  549. continue;
  550. }
  551. if (NumberOfConnections < Count)
  552. {
  553. NumberOfConnections = Count;
  554. // Better check space needed to hold NBT data again
  555. // this is because the Count could be hugh
  556. SpaceNeeded = sizeof(NBT_DATA_DEFINITION) +
  557. (NumberOfConnections *
  558. NumberOfNbtDevices *
  559. (sizeof(PERF_INSTANCE_DEFINITION) +
  560. QWORD_MULTIPLE((NBT_CONNECTION_NAME_LENGTH + 1) * sizeof(WCHAR)) +
  561. QWORD_MULTIPLE(MaxNbtDeviceName )
  562. + SIZE_OF_NBT_DATA));
  563. if ( *lpcbTotalBytes < SpaceNeeded ) {
  564. dwDataReturn[0] = *lpcbTotalBytes;
  565. dwDataReturn[1] = SpaceNeeded;
  566. REPORT_WARNING_DATA (NBT_DATA_BUFFER_SIZE, LOG_DEBUG,
  567. &dwDataReturn, sizeof (dwDataReturn));
  568. return ERROR_MORE_DATA;
  569. }
  570. }
  571. while ( Count-- )
  572. {
  573. if (pConns->State == NBT_SESSION_UP)
  574. {
  575. // only care about UP connection
  576. if (pConns->RemoteName[0])
  577. {
  578. AnsiConnectionName.Length = (USHORT)sprintf (
  579. AnsiConnectionNameBuffer,
  580. "%16.16s",
  581. printable(pConns->RemoteName, NameOut));
  582. }
  583. else if (pConns->LocalName[0])
  584. {
  585. if (pConns->LocalName[NETBIOS_NAME_SIZE-1] < ' ')
  586. {
  587. AnsiConnectionName.Length = (USHORT)sprintf (
  588. AnsiConnectionNameBuffer,
  589. "%15.15s%02.2X",
  590. printable(pConns->LocalName, NameOut),
  591. pConns->LocalName[NETBIOS_NAME_SIZE-1]);
  592. }
  593. else
  594. {
  595. AnsiConnectionName.Length = (USHORT)sprintf (
  596. AnsiConnectionNameBuffer,
  597. "%16.16s",
  598. printable(pConns->LocalName, NameOut));
  599. }
  600. }
  601. else
  602. {
  603. AnsiConnectionNameBuffer[0] = ' ';
  604. AnsiConnectionName.Length = 1;
  605. }
  606. ConnectionName.Length =
  607. ConnectionName.MaximumLength =
  608. sizeof(ConnectionNameBuffer);
  609. ConnectionName.Buffer = ConnectionNameBuffer;
  610. RtlAnsiStringToUnicodeString (&ConnectionName,
  611. &AnsiConnectionName,
  612. FALSE);
  613. // no need to put in device name since we can
  614. // only support one device
  615. #if 0
  616. lstrcpyW (DeviceNameBuffer, pNbtDeviceData[i].DeviceName.Buffer);
  617. lstrcatW (DeviceNameBuffer, L" ");
  618. lstrcatW (DeviceNameBuffer, ConnectionNameBuffer);
  619. ConnectionName.Length =
  620. lstrlenW (DeviceNameBuffer) * sizeof(WCHAR);
  621. ConnectionName.MaximumLength =
  622. sizeof(DeviceNameBuffer);
  623. ConnectionName.Buffer = DeviceNameBuffer;
  624. #endif
  625. //
  626. // load instance data into buffer
  627. //
  628. MonBuildInstanceDefinition (pPerfInstanceDefinition,
  629. (PVOID *) &pPerfCounterBlock,
  630. 0,
  631. 0,
  632. (DWORD)PERF_NO_UNIQUE_ID, // no unique ID, Use the name instead
  633. // ConnectionCounter++,
  634. &ConnectionName);
  635. //
  636. // adjust object size values to include new instance
  637. //
  638. pNbtObject->NumInstances++;
  639. //
  640. // initialize this instance's counter block
  641. pPerfCounterBlock->ByteLength = SIZE_OF_NBT_DATA;
  642. pliCounter = (LARGE_INTEGER UNALIGNED * ) (pPerfCounterBlock + 2);
  643. *(pliCounter++) = pConns->BytesRcvd;
  644. TotalReceived.QuadPart = TotalReceived.QuadPart +
  645. pConns->BytesRcvd.QuadPart;
  646. *pliCounter++ = pConns->BytesSent;
  647. TotalSent.QuadPart = TotalSent.QuadPart +
  648. pConns->BytesSent.QuadPart;
  649. pliCounter->QuadPart = pConns->BytesRcvd.QuadPart +
  650. pConns->BytesSent.QuadPart;
  651. //
  652. // update pointer for next instance
  653. //
  654. pPerfInstanceDefinition = (PERF_INSTANCE_DEFINITION *)
  655. (((PBYTE) pPerfCounterBlock) + SIZE_OF_NBT_DATA);
  656. } // pConns->State == NBT_SESSION_UP
  657. pConns++;
  658. } // while ( Count-- )
  659. } // for i < NumberOfNbtDevices
  660. // The last instance definition contains the total data from all the
  661. // displayed connections
  662. RtlInitUnicodeString (&ConnectionName, TotalName);
  663. MonBuildInstanceDefinition (pPerfInstanceDefinition,
  664. (PVOID *) &pPerfCounterBlock,
  665. 0,
  666. 0,
  667. // ConnectionCounter++,
  668. (DWORD)PERF_NO_UNIQUE_ID, // no unique ID, Use the name instead
  669. &ConnectionName);
  670. //
  671. // adjust object size values to include new instance
  672. //
  673. pNbtObject->NumInstances++;
  674. pNbtObject->TotalByteLength += sizeof (PERF_INSTANCE_DEFINITION)
  675. + SIZE_OF_NBT_DATA;
  676. // initialize counter block for this instance
  677. pPerfCounterBlock->ByteLength = SIZE_OF_NBT_DATA;
  678. // load counters
  679. pliCounter = (LARGE_INTEGER UNALIGNED * ) (pPerfCounterBlock + 2);
  680. (*(pliCounter++)) = TotalReceived;
  681. (*(pliCounter++)) = TotalSent;
  682. pliCounter->QuadPart = TotalReceived.QuadPart + TotalSent.QuadPart;
  683. pliCounter++;
  684. // Set returned values
  685. *lppData = (LPVOID)pliCounter;
  686. *lpNumObjectTypes = NBT_NUM_PERF_OBJECT_TYPES;
  687. *lpcbTotalBytes = (DWORD)((LPBYTE)pliCounter-(LPBYTE)pNbtObject);
  688. pNbtDataDefinition->NbtObjectType.TotalByteLength = *lpcbTotalBytes;
  689. REPORT_INFORMATION (NBT_COLLECT_DATA, LOG_DEBUG);
  690. return ERROR_SUCCESS;
  691. }
  692. DWORD
  693. CloseNbtPerformanceData(
  694. )
  695. /*++
  696. Routine Description:
  697. This routine closes the open handles to Nbt devices.
  698. Arguments:
  699. None.
  700. Return Value:
  701. ERROR_SUCCESS
  702. --*/
  703. {
  704. int i;
  705. REPORT_INFORMATION (NBT_CLOSE, LOG_VERBOSE);
  706. if (InterlockedDecrement(&dwNbtRefCount) == 0) {
  707. if (pNbtDeviceData) {
  708. for (i=0; i < NumberOfNbtDevices; i++) {
  709. if (pNbtDeviceData[i].DeviceName.Buffer) {
  710. RtlFreeUnicodeString(&(pNbtDeviceData[i].DeviceName));
  711. }
  712. if (pNbtDeviceData[i].hFileHandle) {
  713. NtClose (pNbtDeviceData[i].hFileHandle);
  714. }
  715. }
  716. RtlFreeHeap( RtlProcessHeap(), 0, pNbtDeviceData);
  717. pNbtDeviceData = NULL;
  718. NumberOfNbtDevices = 0;
  719. }
  720. if (pNbtDataBuffer) {
  721. RtlFreeHeap( RtlProcessHeap(), 0, pNbtDataBuffer);
  722. pNbtDataBuffer = NULL;
  723. NbtDataBufferSize = 0;
  724. }
  725. }
  726. MonCloseEventLog();
  727. return ERROR_SUCCESS;
  728. }