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.

2099 lines
52 KiB

  1. /*++
  2. Copyright (c) 1992, 1993 Microsoft Corporation
  3. Module Name:
  4. nbtinfo.c
  5. Abstract:
  6. This module implements the statistics gathering and display for NBT.
  7. Author:
  8. Jim Stewart November 18 22, 1993
  9. Revision History:
  10. Shirish Koti June 17, 1994 Modified to make code common between
  11. NT and VxD
  12. MohsinA, 06-Dec-96. Synchronize stdout and stderr, messages.
  13. added nls_printf().
  14. MohsinA, 19-Mar-97. Cleanup mutli adaptor fix (index).
  15. Notes:
  16. --*/
  17. #include "nlstxt.h"
  18. #ifdef CHICAGO_PRODUCT
  19. #include "tdistat.h"
  20. #endif // CHICAGO_PRODUCT
  21. #include "nbtstat.h"
  22. #ifndef CHICAGO_PRODUCT
  23. #include "nls.h"
  24. #include "nhapi.h"
  25. #endif // !CHICAGO_PRODUCT
  26. #if defined(DBG) || defined(DEBUG)
  27. #define DEBUG_PRINT(S) printf S
  28. #else
  29. #define DEBUG_PRINT(S) /* nothing */
  30. #endif
  31. #if DBG
  32. #define NT_DEBUG_PRINT(S) printf S
  33. #else
  34. #define NT_DEBUG_PRINT(S) /* nothing */
  35. #endif
  36. CHAR pScope[MAX_NAME];
  37. /**********************************************************************/
  38. /*
  39. * The following option combinations are possible:
  40. *
  41. * (default) Display active connections.
  42. * -c List NetBIOS remote name cache, showing dotted decimal ip addresses
  43. * -N List local NetBIOS names
  44. * -n List local NetBIOS names
  45. * -R Rsync Remote NetBIOS name cache
  46. * -r Names resolved via broadcast and via WINS
  47. * -s List Netbios Sessions converting IpAddresses through Hosts file
  48. * -S List Netbios Sessions with IP Addresses
  49. * -RR Send Name Release packets to WINS and then, start Refresh
  50. *
  51. */
  52. int display = CONNECTION; /* things to display */
  53. char *state();
  54. char *type();
  55. char *name_type();
  56. char *status();
  57. char *expand();
  58. int usage(void);
  59. char *expand(char *stretch, int len, char *code);
  60. char *printable(char *string,char *strout);
  61. BOOLEAN IsInteger(char *string);
  62. #define BUFF_SIZE 650
  63. ULONG NumDevices = 0;
  64. ULONG NetbtIpAddress;
  65. #ifndef CHICAGO_PRODUCT
  66. CHAR pDeviceInfo[NBT_MAXIMUM_BINDINGS+1][MAX_NAME+1];
  67. #else
  68. ULONG pDeviceInfo[NBT_MAXIMUM_BINDINGS+1] = {0};
  69. #define VNBT_Device_ID 0x049B
  70. HANDLE gNbtVxdHandle;
  71. #endif // !CHICAGO_PRODUCT
  72. #define dim(X) (sizeof(X)/sizeof((X)[0]))
  73. LPSTR MapAdapterGuidToName(LPSTR AdapterNameM)
  74. {
  75. static CHAR AdapterFriendlyNameM[MAX_NAME + 1];
  76. ULONG i;
  77. LPSTR AdapterGuidM;
  78. GUID Guid;
  79. UNICODE_STRING AdapterGuidU;
  80. WCHAR AdapterGuidW[MAX_NAME+1];
  81. WCHAR AdapterFriendlyNameW[MAX_NAME+1];
  82. DWORD Size = dim(AdapterFriendlyNameW);
  83. //
  84. // Get the GUID out of the device name string
  85. //
  86. for (i = strlen(AdapterNameM); i != 0; i--)
  87. {
  88. if (AdapterNameM[i] == '{')
  89. {
  90. break;
  91. }
  92. }
  93. if (i == 0)
  94. {
  95. return AdapterNameM;
  96. }
  97. AdapterGuidM = &AdapterNameM[i];
  98. i = MultiByteToWideChar (CP_ACP, 0, AdapterGuidM, -1, AdapterGuidW, dim(AdapterGuidW));
  99. if (i <= 0)
  100. {
  101. return AdapterNameM;
  102. }
  103. RtlInitUnicodeString (&AdapterGuidU, AdapterGuidW);
  104. if (STATUS_SUCCESS != RtlGUIDFromString (&AdapterGuidU, &Guid))
  105. {
  106. return AdapterNameM;
  107. }
  108. if (NO_ERROR != NhGetInterfaceNameFromDeviceGuid (&Guid, AdapterFriendlyNameW, &Size, FALSE, TRUE))
  109. {
  110. return AdapterNameM;
  111. }
  112. WideCharToMultiByte (CP_ACP, 0, AdapterFriendlyNameW, -1, AdapterFriendlyNameM, sizeof(AdapterFriendlyNameM), NULL,NULL);
  113. return (AdapterFriendlyNameM);
  114. }
  115. // ========================================================================
  116. #define LEN_DbgPrint 1000
  117. void
  118. nls_printf(
  119. char * format,
  120. ...
  121. )
  122. {
  123. va_list ap;
  124. char message[LEN_DbgPrint];
  125. int message_len;
  126. va_start( ap, format );
  127. message_len = vsprintf( message, format, ap );
  128. va_end( ap );
  129. assert( message_len < LEN_DbgPrint );
  130. NlsPutMsg( STDOUT, IDS_PLAIN_STRING, message );
  131. }
  132. /***************************** M A I N ******************************/
  133. __cdecl
  134. main( int argc, char * argv[] )
  135. {
  136. NTSTATUS status;
  137. LONG interval=-1;
  138. UCHAR RemoteName[50];
  139. CHAR HostAddr[20];
  140. PUCHAR Addr;
  141. HANDLE NbtHandle = 0;
  142. ULONG index;
  143. DEBUG_PRINT(("FILE %s\nBuilt on %s at %s\n", __FILE__, __DATE__, __TIME__));
  144. //
  145. // Process arguments to determine which statistics to gather.
  146. // Optional parameter is interval between statistics updates.
  147. // Default is to display statistics once only.
  148. //
  149. if (argc == 1)
  150. {
  151. exit(usage());
  152. }
  153. display = 0;
  154. while (--argc, *++argv)
  155. {
  156. if ((argv[0][0] == '-') || (argv[0][0] == '/')) // process option string
  157. {
  158. register char c, *p = *argv+1;
  159. int arg_exhausted = 0;
  160. if (*p == '\0')
  161. {
  162. exit(usage());
  163. }
  164. //
  165. // Loop along this set of flags.
  166. //
  167. while (!arg_exhausted && (c = *p++))
  168. {
  169. switch (c)
  170. {
  171. case 'a':
  172. case 'A':
  173. display = ADAPTERSTATUS;
  174. //
  175. // "A" - this means the user has given us an IP address
  176. // rather than a name to do an adapter status to.
  177. //
  178. if (c == 'A')
  179. {
  180. display = ADAPTERSTATUSIP;
  181. }
  182. RemoteName[0] = '\0';
  183. if (--argc)
  184. {
  185. *++argv;
  186. p = *argv;
  187. if ((p) && (*p) && (strlen(p) < sizeof(RemoteName)))
  188. {
  189. strcpy(RemoteName,p);
  190. }
  191. else
  192. {
  193. DEBUG_PRINT(("invalid name or ip address\n"));
  194. exit(usage());
  195. }
  196. arg_exhausted = TRUE;
  197. }
  198. else
  199. {
  200. DEBUG_PRINT(("Need name or ip address\n"));
  201. }
  202. break;
  203. case 'c':
  204. display = CACHE;
  205. break;
  206. case 'n':
  207. case 'N':
  208. display = NAMES;
  209. break;
  210. case 'r':
  211. display = BCAST;
  212. break;
  213. case 'R':
  214. if (*p == 'R')
  215. {
  216. p++;
  217. display = NAME_RELEASE_REFRESH;
  218. }
  219. else
  220. {
  221. display = RESYNC;
  222. }
  223. break;
  224. case 's':
  225. display = CONNECTION;
  226. break;
  227. case 'S':
  228. display = CONNECTION_WITH_IP;
  229. break;
  230. default: /* unrecognized flag */
  231. DEBUG_PRINT(("Unrecognized flag %s\n", argv[0] ));
  232. exit(usage());
  233. }
  234. }
  235. }
  236. else if (IsInteger(*argv))
  237. {
  238. interval = (int) atoi( * argv );
  239. }
  240. else
  241. {
  242. DEBUG_PRINT(("invalid time interval\n"));
  243. exit(usage());
  244. }
  245. } // while (argc ...)
  246. if ( display == 0 )
  247. {
  248. DEBUG_PRINT(("nothing to display?\n"));
  249. exit(usage());
  250. }
  251. // ====================================================================
  252. //
  253. // Get the list of interfaces to which NetBT is currently bound
  254. //
  255. status = GetInterfaceList ();
  256. if (!NT_SUCCESS(status))
  257. {
  258. NlsPutMsg(STDERR, IDS_FAILURE_NBT_DRIVER);
  259. exit(1);
  260. }
  261. if (0 == NumDevices)
  262. {
  263. NlsPutMsg(STDERR, IDS_FAILED_NBT_NO_DEVICES);
  264. exit(1);
  265. }
  266. //
  267. // Loop forever, sleeping for "interval" seconds between cycles.
  268. // If (interval < 0), return after one cycle.
  269. //
  270. // Note that we're nice boys who close all devices while we're
  271. // sleeping (after all, it is possible to say "netstat 5000"!).
  272. // This probably doesn't help much, but it's a nice gesture...
  273. //
  274. do
  275. {
  276. for (index=0; index < NumDevices; index++)
  277. {
  278. //
  279. // Open the device of the appropriate streams module to start with.
  280. //
  281. NbtHandle = OpenNbt (index);
  282. if (NbtHandle < 0)
  283. {
  284. if (!(display & (BCAST | RESYNC)))
  285. {
  286. #ifndef CHICAGO_PRODUCT
  287. nls_printf ("\tFailed to access NBT Device %s",
  288. MapAdapterGuidToName (pDeviceInfo[index]));
  289. #else
  290. nls_printf ("\tFailed to access NBT Device, Lana # %d",
  291. NbtHandle);
  292. #endif // CHICAGO_PRODUCT
  293. }
  294. //
  295. // Try the next binding!
  296. //
  297. continue;
  298. }
  299. GetIpAddress (NbtHandle,&NetbtIpAddress);
  300. Addr = (PUCHAR) &NetbtIpAddress;
  301. //
  302. // print out the Device name + Ip Address of this node
  303. //
  304. if (!(display & (BCAST | RESYNC | NAME_RELEASE_REFRESH)))
  305. {
  306. #ifndef CHICAGO_PRODUCT
  307. nls_printf ("\n%s:\n", MapAdapterGuidToName (pDeviceInfo[index]));
  308. #else
  309. nls_printf ("\nLana # %d:\n", pDeviceInfo[index]);
  310. #endif // CHICAGO_PRODUCT
  311. sprintf(HostAddr,"%d.%d.%d.%d", Addr[3], Addr[2], Addr[1], Addr[0]);
  312. NlsPutMsg(STDOUT, IDS_STATUS_FIELDS, HostAddr, pScope);
  313. }
  314. switch (display)
  315. {
  316. case ADAPTERSTATUS:
  317. case ADAPTERSTATUSIP:
  318. if (RemoteName[0] == '\0')
  319. {
  320. usage();
  321. interval = -1;
  322. }
  323. else
  324. {
  325. status = AdapterStatusIpAddr (NbtHandle, RemoteName, display);
  326. }
  327. break;
  328. case BCAST:
  329. status = GetBcastResolvedNames (NbtHandle);
  330. break;
  331. case CACHE:
  332. case NAMES:
  333. status = GetNames(NbtHandle, display);
  334. break;
  335. case RESYNC:
  336. status = Resync (NbtHandle);
  337. break;
  338. case NAME_RELEASE_REFRESH:
  339. status = ReleaseNamesThenRefresh (NbtHandle);
  340. break;
  341. case CONNECTION:
  342. case CONNECTION_WITH_IP:
  343. status = GetConnections (NbtHandle,display);
  344. break;
  345. default:
  346. usage();
  347. interval = -1;
  348. break;
  349. } // switch
  350. #ifndef CHICAGO_PRODUCT
  351. NtClose (NbtHandle); // Close everything while we sleep.
  352. #endif
  353. if (display & (BCAST | RESYNC | NAME_RELEASE_REFRESH))
  354. {
  355. if (NT_SUCCESS (status))
  356. {
  357. break; // break only for the case(s) above
  358. }
  359. }
  360. } // for (index ...)
  361. //
  362. // Go to sleep for the appropriate interval until the
  363. // next round, or exit if this is a once-only job.
  364. //
  365. if (interval > 0)
  366. {
  367. Sleep (interval*1000); // ms.
  368. }
  369. } while (interval > 0);
  370. #ifdef CHICAGO_PRODUCT
  371. if (!CloseHandle (gNbtVxdHandle))
  372. {
  373. DEBUG_PRINT(("CloseHandle FAILed: Handle=<%x>, Error=<%x>\n", gNbtVxdHandle, GetLastError()));
  374. }
  375. #endif // CHICAGO_PRODUCT
  376. return 0;
  377. }
  378. /* =======================================================================
  379. * IsInteger
  380. *
  381. * ENTRY Parameter - pointer to string
  382. *
  383. * EXIT
  384. *
  385. * RETURNS TRUE if Parameter is a valid integer
  386. *
  387. * ASSUMES
  388. *
  389. */
  390. BOOLEAN
  391. IsInteger(
  392. char *Parameter
  393. )
  394. {
  395. while (*Parameter != '\0')
  396. {
  397. if ((*Parameter < '0') || (*Parameter > '9'))
  398. {
  399. return (FALSE);
  400. }
  401. Parameter++;
  402. }
  403. return (TRUE);
  404. }
  405. /* =======================================================================
  406. * name_type() -- describe NBT Name types
  407. *
  408. */
  409. char *
  410. name_type(int t)
  411. {
  412. static int first_time = 1;
  413. static char group[32];
  414. static char unique[32];
  415. if (first_time) {
  416. first_time = 0;
  417. NlsSPrintf(IDS_NAMETYPE_GROUP, group, sizeof(group)-1);
  418. NlsSPrintf(IDS_NAMETYPE_UNIQUE, unique, sizeof(unique)-1);
  419. }
  420. if (t & GROUP_NAME) return group;
  421. else return unique;
  422. }
  423. /* ========================================================================
  424. * NameStatus() -- describe NBT Name status
  425. *
  426. */
  427. char *
  428. NameStatus(int s)
  429. {
  430. switch(s & 0x0F)
  431. {
  432. case DUPLICATE_DEREG: return("CONFLICT DEREGISTERED");
  433. case DUPLICATE: return("CONFLICT");
  434. case REGISTERING: return("REGISTERING");
  435. case DEREGISTERED: return("DEREGISTERED");
  436. case REGISTERED: return("REGISTERED");
  437. default: return("?");
  438. }
  439. }
  440. /* ========================================================================
  441. * usage() -- print out a standard usage message
  442. */
  443. int
  444. usage(void)
  445. {
  446. //fprintf(stderr, "%s", args);
  447. NlsPutMsg(STDERR, IDS_USAGE);
  448. return(2);
  449. }
  450. //------------------------------------------------------------------------
  451. /*++
  452. Routine Description:
  453. This procedure converts non prinatble characaters to periods ('.')
  454. Arguments:
  455. string - the string to convert
  456. StrOut - ptr to a string to put the converted string into
  457. Return Value:
  458. a ptr to the string that was converted (Strout)
  459. --*/
  460. PCHAR
  461. printable(
  462. IN PCHAR string,
  463. IN PCHAR StrOut
  464. )
  465. {
  466. unsigned char *Out;
  467. unsigned char *cp;
  468. LONG i;
  469. Out = StrOut;
  470. for (cp = string, i= 0; i < NETBIOS_NAME_SIZE; cp++,i++)
  471. {
  472. if (isprint(*cp))
  473. {
  474. *Out++ = *cp;
  475. continue;
  476. }
  477. if (*cp >= 128) // extended characters are ok
  478. {
  479. *Out++ = *cp;
  480. continue;
  481. }
  482. *Out++ = '.';
  483. }
  484. //
  485. // Convert to Ansi since NlsPutMsg will convert back to Oem
  486. // Bug # 170935
  487. //
  488. OemToCharBuffA(StrOut, StrOut, NETBIOS_NAME_SIZE);
  489. return(StrOut);
  490. }
  491. //------------------------------------------------------------------------
  492. /*++
  493. Routine Description:
  494. This function calls into netbt to get the ip address.
  495. Arguments:
  496. fd - file handle to netbt
  497. pIpAddress - the ip address returned
  498. Return Value:
  499. ntstatus
  500. --*/
  501. NTSTATUS
  502. GetIpAddress(
  503. IN HANDLE fd,
  504. OUT PULONG pIpAddress
  505. )
  506. {
  507. NTSTATUS status;
  508. ULONG BufferSize=100;
  509. PVOID pBuffer;
  510. pBuffer = LocalAlloc(LMEM_FIXED,BufferSize);
  511. if (!pBuffer)
  512. {
  513. return(STATUS_INSUFFICIENT_RESOURCES);
  514. }
  515. status = STATUS_BUFFER_OVERFLOW;
  516. status = CALL_DRIVER(fd,
  517. pBuffer,
  518. BufferSize,
  519. IOCTL_NETBT_GET_IP_ADDRS,
  520. NULL,
  521. 0);
  522. if (STATUS_SUCCESS == status)
  523. {
  524. *pIpAddress = *(ULONG *)pBuffer;
  525. }
  526. else
  527. {
  528. *pIpAddress = 0;
  529. }
  530. LocalFree(pBuffer);
  531. return(status);
  532. }
  533. //------------------------------------------------------------------------
  534. /*++
  535. Routine Description:
  536. This procedure does an adapter status query to get the local name table.
  537. It either prints out the local name table or the remote (cache) table
  538. depending on whether WhichNames is NAMES or CACHE .
  539. Arguments:
  540. Return Value:
  541. 0 if successful, -1 otherwise.
  542. --*/
  543. NTSTATUS
  544. GetNames(
  545. IN HANDLE fd,
  546. IN LONG WhichNames
  547. )
  548. {
  549. LONG Count;
  550. PVOID pBuffer;
  551. ULONG BufferSize=600;
  552. NTSTATUS status;
  553. tADAPTERSTATUS *pAdapterStatus;
  554. PUCHAR Addr;
  555. ULONG Ioctl;
  556. TDI_REQUEST_QUERY_INFORMATION QueryInfo;
  557. PVOID pInput;
  558. ULONG SizeInput;
  559. NAME_BUFFER UNALIGNED *pNames;
  560. CHAR HostAddr[20];
  561. CHAR NameOut[NETBIOS_NAME_SIZE +4];
  562. pBuffer = LocalAlloc(LMEM_FIXED,BufferSize);
  563. if (!pBuffer)
  564. {
  565. return(STATUS_INSUFFICIENT_RESOURCES);
  566. }
  567. status = STATUS_BUFFER_OVERFLOW;
  568. //
  569. // set the correct Ioctl for the call to NBT, to get either
  570. // the local name table or the remote name table
  571. //
  572. if (WhichNames == NAMES)
  573. {
  574. #ifndef CHICAGO_PRODUCT
  575. Ioctl = IOCTL_TDI_QUERY_INFORMATION;
  576. #else
  577. Ioctl = IOCTL_NETBT_GET_LOCAL_NAMES;
  578. #endif
  579. QueryInfo.QueryType = TDI_QUERY_ADAPTER_STATUS; // node status or whatever
  580. SizeInput = sizeof(TDI_REQUEST_QUERY_INFORMATION);
  581. pInput = &QueryInfo;
  582. }
  583. else
  584. {
  585. Ioctl = IOCTL_NETBT_GET_REMOTE_NAMES;
  586. SizeInput = 0;
  587. pInput = NULL;
  588. }
  589. while (status == STATUS_BUFFER_OVERFLOW)
  590. {
  591. status = CALL_DRIVER(fd,
  592. pBuffer,
  593. BufferSize,
  594. Ioctl,
  595. pInput,
  596. SizeInput);
  597. if (status == STATUS_BUFFER_OVERFLOW)
  598. {
  599. LocalFree(pBuffer);
  600. BufferSize *=2;
  601. if ((BufferSize >= 0xFFFF) ||
  602. (!(pBuffer = LocalAlloc(LMEM_FIXED,BufferSize))))
  603. {
  604. NlsPerror(COMMON_UNABLE_TO_ALLOCATE_PACKET,0);
  605. return(STATUS_INSUFFICIENT_RESOURCES);
  606. }
  607. }
  608. }
  609. pAdapterStatus = (tADAPTERSTATUS *)pBuffer;
  610. if ((pAdapterStatus->AdapterInfo.name_count == 0) ||
  611. (status != STATUS_SUCCESS))
  612. {
  613. LocalFree(pBuffer);
  614. NlsPutMsg(STDOUT,IDS_NONAMES_INCACHE);
  615. return(status);
  616. }
  617. if (WhichNames & NAMES)
  618. {
  619. NlsPutMsg(STDOUT, IDS_NETBIOS_LOCAL_STATUS);
  620. }
  621. else
  622. {
  623. NlsPutMsg(STDOUT, IDS_NETBIOS_REMOTE_STATUS);
  624. }
  625. pNames = pAdapterStatus->Names;
  626. Count = pAdapterStatus->AdapterInfo.name_count;
  627. while(Count--)
  628. {
  629. nls_printf("%-15.15s<%02.2X> %-10s ",
  630. printable(pNames->name,NameOut), pNames->name[NETBIOS_NAME_SIZE-1],name_type(pNames->name_flags));
  631. if (WhichNames == CACHE)
  632. {
  633. Addr = (PUCHAR) &((tREMOTE_CACHE *)pNames)->IpAddress;
  634. sprintf (HostAddr,"%d.%d.%d.%d", Addr[3], Addr[2], Addr[1], Addr[0]);
  635. nls_printf("%-20.20s" "%-d", HostAddr, *(ULONG UNALIGNED *) &((tREMOTE_CACHE *)pNames)->Ttl);
  636. ((tREMOTE_CACHE *)pNames)++;
  637. }
  638. else
  639. {
  640. switch(pNames->name_flags & 0x0F)
  641. {
  642. case DUPLICATE_DEREG:
  643. NlsPutMsg(STDOUT,IDS_CONFLICT_DEREGISTERED);
  644. break;
  645. case DUPLICATE:
  646. NlsPutMsg(STDOUT,IDS_CONFLICT);
  647. break;
  648. case REGISTERING:
  649. NlsPutMsg(STDOUT,IDS_REGISTERING);
  650. break;
  651. case DEREGISTERED:
  652. NlsPutMsg(STDOUT,IDS_DEREGISTERED);
  653. break;
  654. case REGISTERED:
  655. NlsPutMsg(STDOUT,IDS_REGISTERED);
  656. break;
  657. default:
  658. NlsPutMsg(STDOUT,IDS_DONT_KNOW);
  659. }
  660. pNames++;
  661. }
  662. NlsPutMsg(STDOUT, IDS_NEWLINE );
  663. }
  664. LocalFree(pBuffer);
  665. return(status);
  666. }
  667. //------------------------------------------------------------------------
  668. /*++
  669. Routine Description:
  670. This procedure does an adapter status query to get the remote name table.
  671. Arguments:
  672. Return Value:
  673. 0 if successful, -1 otherwise.
  674. --*/
  675. NTSTATUS
  676. AdapterStatusIpAddr(
  677. IN HANDLE fd,
  678. IN PCHAR RemoteNameA,
  679. IN LONG Display
  680. )
  681. {
  682. LONG Count;
  683. LONG i;
  684. PVOID pBuffer;
  685. ULONG BufferSize=600;
  686. NTSTATUS status;
  687. tADAPTERSTATUS *pAdapterStatus;
  688. NAME_BUFFER *pNames;
  689. CHAR MacAddress[20];
  690. tIPANDNAMEINFO *pIpAndNameInfo;
  691. ULONG SizeInput;
  692. ULONG IpAddress;
  693. OEM_STRING OemName;
  694. WCHAR RemoteNameW[256];
  695. UCHAR RemoteNameOem[256];
  696. UNICODE_STRING RemoteNameU;
  697. USHORT NameLength;
  698. PUCHAR pRemoteName = NULL;
  699. if (!NetbtIpAddress)
  700. {
  701. NlsPutMsg(STDOUT,IDS_MACHINE_NOT_FOUND);
  702. return(STATUS_BAD_NETWORK_PATH);
  703. }
  704. pBuffer = LocalAlloc(LMEM_FIXED,BufferSize);
  705. if (!pBuffer)
  706. {
  707. return(STATUS_INSUFFICIENT_RESOURCES);
  708. }
  709. pIpAndNameInfo = LocalAlloc(LMEM_FIXED,sizeof(tIPANDNAMEINFO));
  710. if (!pIpAndNameInfo)
  711. {
  712. LocalFree(pBuffer);
  713. return(STATUS_INSUFFICIENT_RESOURCES);
  714. }
  715. status = STATUS_BUFFER_OVERFLOW;
  716. RtlZeroMemory((PVOID)pIpAndNameInfo,sizeof(tIPANDNAMEINFO));
  717. if (Display == ADAPTERSTATUSIP)
  718. {
  719. //
  720. // Convert the remote name which is really a dotted decimal ip address
  721. // into a ulong
  722. //
  723. IpAddress = inet_addr(RemoteNameA);
  724. //
  725. // Don't allow zero for the address since it sends a broadcast and
  726. // every one responds
  727. //
  728. if ((IpAddress == INADDR_NONE) || (IpAddress == 0))
  729. {
  730. NlsPutMsg(STDOUT, IDS_BAD_IPADDRESS, RemoteNameA);
  731. LocalFree(pBuffer);
  732. LocalFree(pIpAndNameInfo);
  733. return(STATUS_UNSUCCESSFUL);
  734. }
  735. pIpAndNameInfo->IpAddress = ntohl(IpAddress);
  736. pIpAndNameInfo->NetbiosAddress.Address[0].Address[0].NetbiosName[0] = '*';
  737. }
  738. else
  739. {
  740. //
  741. // the remote name was supplied by the user, so blank pad to the
  742. // right and put a zero on the end to get the workstation name.
  743. //
  744. RtlFillMemory(&pIpAndNameInfo->NetbiosAddress.Address[0].Address[0].NetbiosName[0],
  745. NETBIOS_NAME_SIZE, ' ');
  746. NameLength = (USHORT)strlen(RemoteNameA);
  747. #ifndef CHICAGO_PRODUCT
  748. //
  749. // Convert the name from ANSI to UpperCase OEM (max length = NETBIOS_NAME_SIZE)
  750. // Bug # 409792
  751. //
  752. MultiByteToWideChar (CP_ACP, 0, RemoteNameA, -1, RemoteNameW, 256);
  753. RemoteNameW[255] = UNICODE_NULL; // for safety
  754. RtlInitUnicodeString (&RemoteNameU, RemoteNameW);
  755. OemName.MaximumLength = 255;
  756. OemName.Buffer = RemoteNameOem;
  757. status = RtlUpcaseUnicodeStringToOemString (&OemName, &RemoteNameU, FALSE);
  758. if (NT_SUCCESS (status))
  759. {
  760. status = STATUS_BUFFER_OVERFLOW;
  761. }
  762. NameLength = min (OemName.Length, NETBIOS_NAME_SIZE);
  763. pRemoteName = RemoteNameOem;
  764. #else
  765. //
  766. // Chicago does not appear to have Unicode support ?
  767. //
  768. for (i=0;i < (LONG) NameLength; i++)
  769. {
  770. RemoteNameA[i] = toupper (RemoteNameA[i]);
  771. }
  772. NameLength = min (NameLength, NETBIOS_NAME_SIZE);
  773. pRemoteName = RemoteNameA;
  774. #endif // !CHICAGO_PRODUCT
  775. RtlMoveMemory(&pIpAndNameInfo->NetbiosAddress.Address[0].Address[0].NetbiosName[0],
  776. pRemoteName,
  777. NameLength);
  778. pIpAndNameInfo->NetbiosAddress.Address[0].Address[0].NetbiosName[NETBIOS_NAME_SIZE-1] = 0;
  779. }
  780. pIpAndNameInfo->NetbiosAddress.TAAddressCount = 1;
  781. pIpAndNameInfo->NetbiosAddress.Address[0].AddressLength = sizeof(TDI_ADDRESS_NETBIOS);
  782. pIpAndNameInfo->NetbiosAddress.Address[0].AddressType = TDI_ADDRESS_TYPE_NETBIOS;
  783. pIpAndNameInfo->NetbiosAddress.Address[0].Address[0].NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_UNIQUE;
  784. SizeInput = sizeof(tIPANDNAMEINFO);
  785. while (status == STATUS_BUFFER_OVERFLOW)
  786. {
  787. status = CALL_DRIVER(fd,
  788. pBuffer,
  789. BufferSize,
  790. IOCTL_NETBT_ADAPTER_STATUS,
  791. pIpAndNameInfo,
  792. SizeInput);
  793. if (status == STATUS_BUFFER_OVERFLOW)
  794. {
  795. LocalFree(pBuffer);
  796. BufferSize *=2;
  797. if ((BufferSize >= 0xFFFF) ||
  798. (!(pBuffer = LocalAlloc(LMEM_FIXED,BufferSize))))
  799. {
  800. NlsPerror(COMMON_UNABLE_TO_ALLOCATE_PACKET,0);
  801. LocalFree(pIpAndNameInfo);
  802. return(STATUS_INSUFFICIENT_RESOURCES);
  803. }
  804. }
  805. }
  806. pAdapterStatus = (tADAPTERSTATUS *)pBuffer;
  807. if ((status != STATUS_SUCCESS) ||
  808. (pAdapterStatus->AdapterInfo.name_count == 0))
  809. {
  810. LocalFree(pIpAndNameInfo);
  811. LocalFree(pBuffer);
  812. NlsPutMsg(STDOUT,IDS_MACHINE_NOT_FOUND);
  813. return(status);
  814. }
  815. pNames = pAdapterStatus->Names;
  816. Count = pAdapterStatus->AdapterInfo.name_count;
  817. //
  818. // put out a heading for the table of names
  819. //
  820. NlsPutMsg(STDOUT, IDS_REMOTE_NAMES);
  821. while(Count--)
  822. {
  823. CHAR NameOut[NETBIOS_NAME_SIZE +4];
  824. nls_printf("%-15.15s<%02.2X> %-10s ",
  825. printable(pNames->name,NameOut),
  826. pNames->name[NETBIOS_NAME_SIZE-1],
  827. name_type(pNames->name_flags)
  828. );
  829. switch(pNames->name_flags & 0x0F)
  830. {
  831. case DUPLICATE_DEREG:
  832. NlsPutMsg(STDOUT,IDS_CONFLICT_DEREGISTERED);
  833. break;
  834. case DUPLICATE:
  835. NlsPutMsg(STDOUT,IDS_CONFLICT);
  836. break;
  837. case REGISTERING:
  838. NlsPutMsg(STDOUT,IDS_REGISTERING);
  839. break;
  840. case DEREGISTERED:
  841. NlsPutMsg(STDOUT,IDS_DEREGISTERED);
  842. break;
  843. case REGISTERED:
  844. NlsPutMsg(STDOUT,IDS_REGISTERED);
  845. break;
  846. default:
  847. NlsPutMsg(STDOUT,IDS_DONT_KNOW);
  848. }
  849. pNames++;
  850. NlsPutMsg(STDOUT, IDS_NEWLINE );
  851. }
  852. //
  853. // Dump the MAC address
  854. //
  855. {
  856. PUCHAR a;
  857. a = &pAdapterStatus->AdapterInfo.adapter_address[0];
  858. sprintf(MacAddress,"%02.2X-%02.2X-%02.2X-%02.2X-%02.2X-%02.2X",
  859. a[0],a[1],a[2],a[3],a[4],a[5]);
  860. }
  861. NlsPutMsg(STDOUT, IDS_MAC_ADDRESS, MacAddress);
  862. LocalFree(pIpAndNameInfo);
  863. LocalFree(pBuffer);
  864. return(status);
  865. }
  866. //------------------------------------------------------------------------
  867. /*++
  868. Routine Description:
  869. This procedure does gets the connection information from NBT. If the
  870. Display value indicates CONNECTION_WITH_IP, then only the ip address
  871. of the destination is diplayed, otherwise the name of the destination
  872. host is displayed.
  873. Arguments:
  874. Return Value:
  875. 0 if successful, -1 otherwise.
  876. --*/
  877. NTSTATUS
  878. GetConnections(
  879. IN HANDLE fd,
  880. IN LONG Display
  881. )
  882. {
  883. LONG Count;
  884. PVOID pBuffer;
  885. ULONG BufferSize=600;
  886. NTSTATUS status;
  887. tCONNECTION_LIST *pConList;
  888. tCONNECTIONS UNALIGNED *pConns;
  889. pBuffer = LocalAlloc(LMEM_FIXED,BufferSize);
  890. if (!pBuffer)
  891. {
  892. return(STATUS_INSUFFICIENT_RESOURCES);
  893. }
  894. status = STATUS_BUFFER_OVERFLOW;
  895. while (status == STATUS_BUFFER_OVERFLOW)
  896. {
  897. status = CALL_DRIVER(fd,
  898. pBuffer,
  899. BufferSize,
  900. IOCTL_NETBT_GET_CONNECTIONS,
  901. NULL,
  902. 0);
  903. if (status == STATUS_BUFFER_OVERFLOW)
  904. {
  905. LocalFree(pBuffer);
  906. BufferSize *=2;
  907. if ((BufferSize >= 0xFFFF) ||
  908. (!(pBuffer = LocalAlloc(LMEM_FIXED,BufferSize))))
  909. {
  910. NlsPerror(COMMON_UNABLE_TO_ALLOCATE_PACKET,0);
  911. return(STATUS_INSUFFICIENT_RESOURCES);
  912. }
  913. }
  914. }
  915. pConList = (tCONNECTION_LIST *)pBuffer;
  916. if ((status != STATUS_SUCCESS) ||
  917. ((Count = pConList->ConnectionCount) == 0) )
  918. {
  919. // printf(" ntstatus = %X\n",status);
  920. NlsPutMsg(STDOUT,IDS_NO_CONNECTIONS);
  921. LocalFree(pBuffer);
  922. return(status);
  923. }
  924. pConns = pConList->ConnList;
  925. //
  926. // put out a heading for the table of names
  927. //
  928. NlsPutMsg(STDOUT, IDS_NETBIOS_CONNECTION_STATUS);
  929. while(Count--)
  930. {
  931. CHAR NameOut[NETBIOS_NAME_SIZE +4];
  932. if (pConns->LocalName[0])
  933. {
  934. if (pConns->LocalName[NETBIOS_NAME_SIZE-1] < ' ')
  935. {
  936. nls_printf("%-15.15s<%02.2X> ",
  937. printable(pConns->LocalName,NameOut),
  938. pConns->LocalName[NETBIOS_NAME_SIZE-1]);
  939. }
  940. else
  941. {
  942. nls_printf("%-16.16s ", printable(pConns->LocalName,NameOut));
  943. }
  944. }
  945. switch (*(ULONG UNALIGNED *) &pConns->State)
  946. {
  947. case NBT_RECONNECTING:
  948. NlsPutMsg(STDOUT,IDS_RECONNECTING);
  949. break;
  950. case NBT_IDLE:
  951. NlsPutMsg(STDOUT,IDS_IDLE);
  952. break;
  953. case NBT_ASSOCIATED:
  954. NlsPutMsg(STDOUT,IDS_ASSOCIATED);
  955. break;
  956. case NBT_CONNECTING:
  957. NlsPutMsg(STDOUT,IDS_CONNECTING);
  958. break;
  959. case NBT_SESSION_OUTBOUND:
  960. NlsPutMsg(STDOUT,IDS_OUTGOING);
  961. break;
  962. case NBT_SESSION_INBOUND:
  963. NlsPutMsg(STDOUT,IDS_INCOMING);
  964. break;
  965. case NBT_SESSION_WAITACCEPT:
  966. NlsPutMsg(STDOUT,IDS_ACCEPTING);
  967. break;
  968. case NBT_SESSION_UP:
  969. NlsPutMsg(STDOUT,IDS_CONNECTED);
  970. break;
  971. case NBT_DISCONNECTING:
  972. NlsPutMsg(STDOUT,IDS_DISCONNECTING);
  973. break;
  974. case NBT_DISCONNECTED:
  975. NlsPutMsg(STDOUT,IDS_DISCONNECTED);
  976. break;
  977. case LISTENING:
  978. NlsPutMsg(STDOUT,IDS_LISTENING);
  979. break;
  980. case UNBOUND:
  981. default:
  982. NlsPutMsg(STDOUT,IDS_UNBOUND);
  983. break;
  984. }
  985. if (*(ULONG UNALIGNED *) &pConns->SrcIpAddr)
  986. {
  987. if (pConns->Originator)
  988. {
  989. NlsPutMsg(STDOUT,IDS_NETBIOS_OUTBOUND);
  990. }
  991. else
  992. {
  993. NlsPutMsg(STDOUT,IDS_NETBIOS_INBOUND);
  994. }
  995. //
  996. // either display the IP address or the Remote host name
  997. //
  998. if (Display & CONNECTION_WITH_IP)
  999. {
  1000. PUCHAR in;
  1001. UCHAR AddrBuff[30];
  1002. in = (PUCHAR)&pConns->SrcIpAddr;
  1003. sprintf(AddrBuff,"%u.%u.%u.%u", (unsigned char) in[0],
  1004. (unsigned char) in[1], (unsigned char) in[2],
  1005. (unsigned char) in[3]);
  1006. nls_printf(" %-19.19s",AddrBuff);
  1007. }
  1008. else
  1009. {
  1010. nls_printf(" %-15.15s<%02.2X>",
  1011. printable(pConns->RemoteName,NameOut),
  1012. pConns->RemoteName[NETBIOS_NAME_SIZE-1]);
  1013. }
  1014. PrintKorM ((PVOID) &pConns->BytesRcvd);
  1015. PrintKorM ((PVOID) &pConns->BytesSent);
  1016. }
  1017. else
  1018. {
  1019. nls_printf(" ");
  1020. }
  1021. NlsPutMsg(STDOUT, IDS_NEWLINE );
  1022. pConns++;
  1023. }
  1024. LocalFree(pBuffer);
  1025. return(status);
  1026. }
  1027. //------------------------------------------------------------------------
  1028. /*++
  1029. Routine Description:
  1030. This procedure tells NBT to purge all names from its remote hash
  1031. table cache.
  1032. Arguments:
  1033. Return Value:
  1034. 0 if successful, -1 otherwise.
  1035. --*/
  1036. NTSTATUS
  1037. Resync(
  1038. IN HANDLE fd
  1039. )
  1040. {
  1041. NTSTATUS status;
  1042. CHAR Buffer;
  1043. status = CALL_DRIVER(fd,
  1044. &Buffer,
  1045. 1,
  1046. IOCTL_NETBT_PURGE_CACHE,
  1047. NULL,
  1048. 0);
  1049. if (status == STATUS_SUCCESS)
  1050. {
  1051. NlsPutMsg(STDOUT,IDS_RESYNC_OK);
  1052. }
  1053. else
  1054. {
  1055. NlsPutMsg(STDOUT,IDS_RESYNC_FAILED);
  1056. }
  1057. return(status);
  1058. }
  1059. //-----------------------------------------------------------------------
  1060. /*++
  1061. Routine Description:
  1062. This procedure tells NBT to release all of its names on this Device and
  1063. then Refresh them.
  1064. Arguments:
  1065. Return Value:
  1066. 0 if successful, -1 otherwise.
  1067. --*/
  1068. NTSTATUS
  1069. ReleaseNamesThenRefresh(
  1070. IN HANDLE fd
  1071. )
  1072. {
  1073. NTSTATUS status;
  1074. CHAR Buffer;
  1075. status = CALL_DRIVER(fd,
  1076. &Buffer,
  1077. 1,
  1078. IOCTL_NETBT_NAME_RELEASE_REFRESH,
  1079. NULL,
  1080. 0);
  1081. if (STATUS_SUCCESS == status)
  1082. {
  1083. NlsPutMsg(STDOUT,IDS_RELEASE_REFRESH_OK);
  1084. }
  1085. else if (status == STATUS_IO_TIMEOUT)
  1086. {
  1087. NlsPutMsg(STDOUT,IDS_RELEASE_REFRESH_TIMEOUT);
  1088. status = STATUS_SUCCESS;
  1089. }
  1090. else
  1091. {
  1092. NlsPutMsg(STDOUT,IDS_RELEASE_REFRESH_ERROR);
  1093. }
  1094. return(status);
  1095. }
  1096. //------------------------------------------------------------------------
  1097. /*++
  1098. Routine Description:
  1099. This procedure tells NBT to purge all names from its remote hash
  1100. table cache.
  1101. Arguments:
  1102. Return Value:
  1103. 0 if successful, -1 otherwise.
  1104. --*/
  1105. NTSTATUS
  1106. GetBcastResolvedNames(
  1107. IN HANDLE fd
  1108. )
  1109. {
  1110. NTSTATUS status;
  1111. tNAMESTATS_INFO Stats;
  1112. tNAME *pName;
  1113. LONG Count;
  1114. UCHAR Value[60];
  1115. status = CALL_DRIVER(fd,
  1116. &Stats,
  1117. sizeof(tNAMESTATS_INFO),
  1118. IOCTL_NETBT_GET_BCAST_NAMES,
  1119. NULL,
  1120. 0);
  1121. if (status != STATUS_SUCCESS)
  1122. {
  1123. NlsPutMsg(STDOUT,IDS_BCASTNAMES_FAILED);
  1124. return(status);
  1125. }
  1126. NlsPutMsg(STDOUT,IDS_NAME_STATS);
  1127. // name query stats
  1128. sprintf(Value,"%d",Stats.Stats[0]);
  1129. NlsPutMsg(STDOUT,IDS_NUM_BCAST_QUERIES,Value);
  1130. sprintf(Value,"%d",Stats.Stats[2]);
  1131. NlsPutMsg(STDOUT,IDS_NUM_WINS_QUERIES,Value);
  1132. // Name Registration stats
  1133. sprintf(Value,"%d",Stats.Stats[1]);
  1134. NlsPutMsg(STDOUT,IDS_NUM_BCAST_REGISTRATIONS,Value);
  1135. sprintf(Value,"%d",Stats.Stats[3]);
  1136. NlsPutMsg(STDOUT,IDS_NUM_WINS_REGISTRATIONS,Value);
  1137. pName = Stats.NamesReslvdByBcast;
  1138. Count = 0;
  1139. // if there are no names, then return.
  1140. if (pName->Name[0] == '\0')
  1141. {
  1142. return(STATUS_SUCCESS);
  1143. }
  1144. NlsPutMsg(STDOUT,IDS_BCAST_NAMES_HEADER);
  1145. while ((Count < SIZE_RESOLVD_BY_BCAST_CACHE) && (pName->Name[0] != '\0'))
  1146. {
  1147. // if the last character is not a space then print it in hex
  1148. //
  1149. if (pName->Name[NETBIOS_NAME_SIZE-1] != ' ')
  1150. {
  1151. nls_printf(" %15.15s<%02.2X>\n",
  1152. pName->Name,
  1153. pName->Name[NETBIOS_NAME_SIZE-1]);
  1154. }
  1155. else
  1156. {
  1157. nls_printf(" %16.16s\n",pName->Name);
  1158. }
  1159. pName++;
  1160. Count++;
  1161. }
  1162. return(status);
  1163. }
  1164. //
  1165. // @@@@@@@@@@------ Begin NT-specific routines ------@@@@@@@@@@@
  1166. //
  1167. #ifndef CHICAGO_PRODUCT
  1168. //------------------------------------------------------------------------
  1169. NTSTATUS
  1170. GetInterfaceList(
  1171. )
  1172. {
  1173. HANDLE StreamHandle;
  1174. OBJECT_ATTRIBUTES ObjectAttributes;
  1175. IO_STATUS_BLOCK IoStatusBlock;
  1176. STRING name_string, AnsiString;
  1177. UNICODE_STRING uc_name_string;
  1178. NTSTATUS status;
  1179. char pNbtWinsDeviceName[MAX_NAME] = "\\Device\\NetBt_Wins_Export";
  1180. PUCHAR SubKeyParms="system\\currentcontrolset\\services\\netbt\\parameters";
  1181. HKEY Key;
  1182. LONG Type;
  1183. ULONG size;
  1184. CHAR pScopeBuffer[BUFF_SIZE];
  1185. PUCHAR Scope="ScopeId";
  1186. NETBT_INTERFACE_INFO *pInterfaceInfo;
  1187. ULONG InterfaceInfoSize=10*sizeof(NETBT_ADAPTER_INDEX_MAP)+sizeof(ULONG);
  1188. PVOID pInput = NULL;
  1189. ULONG SizeInput = 0;
  1190. ULONG index=0;
  1191. LONG i;
  1192. pInterfaceInfo = LocalAlloc(LMEM_FIXED,InterfaceInfoSize);
  1193. if (!pInterfaceInfo)
  1194. {
  1195. return(STATUS_INSUFFICIENT_RESOURCES);
  1196. }
  1197. RtlInitString(&name_string, pNbtWinsDeviceName);
  1198. RtlAnsiStringToUnicodeString(&uc_name_string, &name_string, TRUE);
  1199. InitializeObjectAttributes(
  1200. &ObjectAttributes,
  1201. &uc_name_string,
  1202. OBJ_CASE_INSENSITIVE,
  1203. (HANDLE) NULL,
  1204. (PSECURITY_DESCRIPTOR) NULL
  1205. );
  1206. status = NtCreateFile (&StreamHandle,
  1207. SYNCHRONIZE | GENERIC_EXECUTE,
  1208. &ObjectAttributes,
  1209. &IoStatusBlock,
  1210. NULL,
  1211. FILE_ATTRIBUTE_NORMAL,
  1212. FILE_SHARE_READ | FILE_SHARE_WRITE,
  1213. FILE_OPEN_IF,
  1214. 0,
  1215. NULL,
  1216. 0);
  1217. RtlFreeUnicodeString(&uc_name_string);
  1218. if (!NT_SUCCESS (status))
  1219. {
  1220. LocalFree(pInterfaceInfo);
  1221. return (status);
  1222. }
  1223. do
  1224. {
  1225. status = CALL_DRIVER (StreamHandle,
  1226. pInterfaceInfo,
  1227. InterfaceInfoSize,
  1228. IOCTL_NETBT_GET_INTERFACE_INFO,
  1229. pInput,
  1230. SizeInput);
  1231. if (status == STATUS_BUFFER_OVERFLOW)
  1232. {
  1233. LocalFree(pInterfaceInfo);
  1234. InterfaceInfoSize *=2;
  1235. if ((InterfaceInfoSize >= 0xFFFF) ||
  1236. (!(pInterfaceInfo = LocalAlloc(LMEM_FIXED,InterfaceInfoSize))))
  1237. {
  1238. NtClose(StreamHandle);
  1239. NlsPerror(COMMON_UNABLE_TO_ALLOCATE_PACKET,0);
  1240. return(STATUS_INSUFFICIENT_RESOURCES);
  1241. }
  1242. }
  1243. else if (STATUS_SUCCESS != status)
  1244. {
  1245. LocalFree(pInterfaceInfo);
  1246. NtClose(StreamHandle);
  1247. return(status);
  1248. }
  1249. } while (status == STATUS_BUFFER_OVERFLOW);
  1250. NtClose (StreamHandle);
  1251. for (i=0; i<pInterfaceInfo->NumAdapters; i++)
  1252. {
  1253. RtlInitString(&name_string, NULL);
  1254. RtlInitUnicodeString(&uc_name_string, pInterfaceInfo->Adapter[i].Name);
  1255. if (NT_SUCCESS(RtlUnicodeStringToAnsiString(&name_string, &uc_name_string, TRUE)))
  1256. {
  1257. size = (name_string.Length > MAX_NAME) ? MAX_NAME : name_string.Length;
  1258. strncpy(pDeviceInfo[index], name_string.Buffer, size);
  1259. pDeviceInfo[index][size] = '\0';
  1260. RtlFreeAnsiString (&name_string);
  1261. index++;
  1262. }
  1263. }
  1264. LocalFree(pInterfaceInfo);
  1265. //
  1266. // NULL out the next device string ptr
  1267. //
  1268. if (index < NBT_MAXIMUM_BINDINGS)
  1269. {
  1270. pDeviceInfo[index][0] = '\0';
  1271. }
  1272. NumDevices = index;
  1273. //
  1274. // Read the ScopeId key!
  1275. //
  1276. size = BUFF_SIZE;
  1277. *pScope = '\0'; // By default
  1278. status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1279. SubKeyParms,
  1280. 0,
  1281. KEY_READ,
  1282. &Key);
  1283. if (status == ERROR_SUCCESS)
  1284. {
  1285. // now read the Scope key
  1286. status = RegQueryValueEx(Key, Scope, NULL, &Type, pScopeBuffer, &size);
  1287. if (status == ERROR_SUCCESS)
  1288. {
  1289. strcpy(pScope,pScopeBuffer);
  1290. }
  1291. status = RegCloseKey(Key);
  1292. }
  1293. return (STATUS_SUCCESS);
  1294. }
  1295. //------------------------------------------------------------------------
  1296. /*++
  1297. Routine Description:
  1298. This function opens a stream.
  1299. Arguments:
  1300. path - path to the STREAMS driver
  1301. oflag - currently ignored. In the future, O_NONBLOCK will be
  1302. relevant.
  1303. ignored - not used
  1304. Return Value:
  1305. An NT handle for the stream, or INVALID_HANDLE_VALUE if unsuccessful.
  1306. --*/
  1307. HANDLE
  1308. OpenNbt(
  1309. IN ULONG Index
  1310. )
  1311. {
  1312. HANDLE StreamHandle;
  1313. OBJECT_ATTRIBUTES ObjectAttributes;
  1314. IO_STATUS_BLOCK IoStatusBlock;
  1315. STRING name_string;
  1316. UNICODE_STRING uc_name_string;
  1317. NTSTATUS status;
  1318. assert (Index < NBT_MAXIMUM_BINDINGS);
  1319. if (pDeviceInfo[Index][0] == '\0')
  1320. {
  1321. return ((HANDLE) -1);
  1322. }
  1323. RtlInitString (&name_string, pDeviceInfo[Index]);
  1324. RtlAnsiStringToUnicodeString (&uc_name_string, &name_string, TRUE);
  1325. InitializeObjectAttributes (&ObjectAttributes,
  1326. &uc_name_string,
  1327. OBJ_CASE_INSENSITIVE,
  1328. (HANDLE) NULL,
  1329. (PSECURITY_DESCRIPTOR) NULL);
  1330. status = NtCreateFile (&StreamHandle,
  1331. SYNCHRONIZE | GENERIC_EXECUTE,
  1332. &ObjectAttributes,
  1333. &IoStatusBlock,
  1334. NULL,
  1335. FILE_ATTRIBUTE_NORMAL,
  1336. FILE_SHARE_READ | FILE_SHARE_WRITE,
  1337. FILE_OPEN_IF,
  1338. 0,
  1339. NULL,
  1340. 0);
  1341. RtlFreeUnicodeString (&uc_name_string);
  1342. if (!NT_SUCCESS(status))
  1343. {
  1344. StreamHandle = (HANDLE) -1;
  1345. }
  1346. return (StreamHandle);
  1347. } // OpenNbt
  1348. //------------------------------------------------------------------------
  1349. /*++
  1350. Routine Description:
  1351. This procedure performs an ioctl(I_STR) on a stream.
  1352. Arguments:
  1353. fd - NT file handle
  1354. iocp - pointer to a strioctl structure
  1355. Return Value:
  1356. 0 if successful, -1 otherwise.
  1357. --*/
  1358. NTSTATUS
  1359. DeviceIoCtrl(
  1360. IN HANDLE fd,
  1361. IN PVOID ReturnBuffer,
  1362. IN ULONG BufferSize,
  1363. IN ULONG Ioctl,
  1364. IN PVOID pInput,
  1365. IN ULONG SizeInput
  1366. )
  1367. {
  1368. NTSTATUS status;
  1369. int retval;
  1370. ULONG QueryType;
  1371. IO_STATUS_BLOCK iosb;
  1372. status = NtDeviceIoControlFile (fd, // Handle
  1373. NULL, // Event
  1374. NULL, // ApcRoutine
  1375. NULL, // ApcContext
  1376. &iosb, // IoStatusBlock
  1377. Ioctl, // IoControlCode
  1378. pInput, // InputBuffer
  1379. SizeInput, // InputBufferSize
  1380. (PVOID) ReturnBuffer, // OutputBuffer
  1381. BufferSize); // OutputBufferSize
  1382. if (status == STATUS_PENDING)
  1383. {
  1384. status = NtWaitForSingleObject (fd, // Handle
  1385. TRUE, // Alertable
  1386. NULL); // Timeout
  1387. if (NT_SUCCESS(status))
  1388. {
  1389. status = iosb.Status;
  1390. }
  1391. }
  1392. return(status);
  1393. }
  1394. //------------------------------------------------------------------------
  1395. /*++
  1396. Routine Description:
  1397. This procedure converts to KBytes or Mbytes
  1398. Arguments:
  1399. Return Value:
  1400. 0 if successful, -1 otherwise.
  1401. --*/
  1402. VOID
  1403. PrintKorM(
  1404. IN PVOID pBytesIn
  1405. )
  1406. {
  1407. LARGE_INTEGER BytesIn = *(LARGE_INTEGER UNALIGNED *) pBytesIn;
  1408. LARGE_INTEGER Bytes;
  1409. if (BytesIn.QuadPart > (ULONGLONG)1000)
  1410. {
  1411. Bytes = RtlExtendedLargeIntegerDivide(BytesIn,1000,NULL);
  1412. if (Bytes.QuadPart > (ULONGLONG)1000)
  1413. {
  1414. Bytes = RtlExtendedLargeIntegerDivide(Bytes,1000,NULL);
  1415. if (Bytes.QuadPart > (ULONGLONG)1000)
  1416. {
  1417. Bytes = RtlExtendedLargeIntegerDivide(Bytes,1000,NULL);
  1418. nls_printf("%6dGB ",Bytes.LowPart);
  1419. }
  1420. else
  1421. {
  1422. nls_printf("%6dMB ",Bytes.LowPart);
  1423. }
  1424. }
  1425. else
  1426. {
  1427. nls_printf("%6dKB ",Bytes.LowPart);
  1428. }
  1429. }
  1430. else
  1431. {
  1432. nls_printf("%6dB ",BytesIn.LowPart);
  1433. }
  1434. }
  1435. #else
  1436. //
  1437. // @@@@@@@@@@------ Begin CHICAGO-specific routines ------@@@@@@@@@@@
  1438. //
  1439. /*******************************************************************
  1440. NAME: OsOpenVxdHandle
  1441. SYNOPSIS: Opens a handle to the specified VxD.
  1442. ENTRY: VxdName - The ASCII name of the target VxD.
  1443. VxdId - The unique ID of the target VxD.
  1444. RETURNS: DWORD - A handle to the target VxD if successful,
  1445. 0 if not.
  1446. HISTORY:
  1447. KeithMo 16-Jan-1994 Created.
  1448. DavidKa 18-Apr-1994 Dynamic load.
  1449. ********************************************************************/
  1450. HANDLE
  1451. OsOpenVxdHandle(
  1452. CHAR * VxdName,
  1453. WORD VxdId
  1454. )
  1455. {
  1456. HANDLE VxdHandle;
  1457. CHAR VxdPath[260];
  1458. //
  1459. // Build the VxD path.
  1460. //
  1461. lstrcpy( VxdPath, "\\\\.\\");
  1462. lstrcat( VxdPath, VxdName);
  1463. //
  1464. // Open the device.
  1465. //
  1466. // First try the name without the .VXD extension. This will
  1467. // cause CreateFile to connect with the VxD if it is already
  1468. // loaded (CreateFile will not load the VxD in this case).
  1469. //
  1470. VxdHandle = CreateFile (VxdPath,
  1471. GENERIC_READ | GENERIC_WRITE,
  1472. FILE_SHARE_READ | FILE_SHARE_WRITE,
  1473. NULL,
  1474. OPEN_EXISTING,
  1475. FILE_FLAG_DELETE_ON_CLOSE,
  1476. NULL );
  1477. if (VxdHandle == INVALID_HANDLE_VALUE)
  1478. {
  1479. //
  1480. // Not found. Append the .VXD extension and try again.
  1481. // This will cause CreateFile to load the VxD.
  1482. //
  1483. lstrcat( VxdPath, ".VXD" );
  1484. VxdHandle = CreateFile( VxdPath,
  1485. GENERIC_READ | GENERIC_WRITE,
  1486. FILE_SHARE_READ | FILE_SHARE_WRITE,
  1487. NULL,
  1488. OPEN_EXISTING,
  1489. FILE_FLAG_DELETE_ON_CLOSE,
  1490. NULL );
  1491. }
  1492. if (VxdHandle != INVALID_HANDLE_VALUE)
  1493. {
  1494. return VxdHandle;
  1495. }
  1496. DEBUG_PRINT(("OsOpenVxdHandle: cannot open %s (%04X), error %d\n", VxdPath, VxdId, GetLastError()));
  1497. return 0;
  1498. } // OsOpenVxdHandle
  1499. //------------------------------------------------------------------------
  1500. /*++
  1501. Routine Description:
  1502. This procedure gets the entry point into the vxd (we call into this entry
  1503. point for all the ioctl needs)
  1504. Arguments:
  1505. VxdEntryProc: pointer to receive the entry point
  1506. Return Value:
  1507. 0 if successful, -1 otherwise.
  1508. --*/
  1509. NTSTATUS
  1510. GetInterfaceList(
  1511. )
  1512. {
  1513. NETBT_INTERFACE_INFO *pInterfaceInfo;
  1514. ULONG InterfaceInfoSize= sizeof(ULONG) + (NBT_MAXIMUM_BINDINGS+1)*sizeof(NETBT_ADAPTER_INDEX_MAP);
  1515. PVOID pInput = NULL;
  1516. ULONG i, SizeInput = 0;
  1517. NTSTATUS status = STATUS_UNSUCCESSFUL;
  1518. if (!(pInterfaceInfo = LocalAlloc(LMEM_FIXED,InterfaceInfoSize)))
  1519. {
  1520. return(STATUS_INSUFFICIENT_RESOURCES);
  1521. }
  1522. RtlZeroMemory ((PVOID)pInterfaceInfo, InterfaceInfoSize);
  1523. if (gNbtVxdHandle = OsOpenVxdHandle("VNBT", VNBT_Device_ID))
  1524. {
  1525. status = CALL_DRIVER ((HANDLE) -1,
  1526. pInterfaceInfo,
  1527. InterfaceInfoSize,
  1528. IOCTL_NETBT_GET_INTERFACE_INFO,
  1529. pInput,
  1530. SizeInput);
  1531. if (STATUS_SUCCESS != status)
  1532. {
  1533. CloseHandle (gNbtVxdHandle);
  1534. gNbtVxdHandle = NULL;
  1535. }
  1536. }
  1537. if (STATUS_SUCCESS == status)
  1538. {
  1539. for (i=0; i<pInterfaceInfo->NumAdapters; i++)
  1540. {
  1541. pDeviceInfo[i] = pInterfaceInfo->Adapter[i].LanaNumber;
  1542. }
  1543. NumDevices = pInterfaceInfo->NumAdapters;
  1544. }
  1545. LocalFree(pInterfaceInfo);
  1546. return status;
  1547. }
  1548. //------------------------------------------------------------------------
  1549. HANDLE
  1550. OpenNbt(
  1551. IN ULONG Index
  1552. )
  1553. {
  1554. return ((HANDLE) pDeviceInfo[Index]);
  1555. }
  1556. //------------------------------------------------------------------------
  1557. /*++
  1558. Routine Description:
  1559. This procedure is a wrapper which makes the calls to the entry point
  1560. Arguments:
  1561. VxdEntryProc: pointer the entry point
  1562. pOutBuffer : buffer to receive data in from the vxd, if applicable
  1563. OutBufLen : length of the output buffer
  1564. Ioctl : what request is this?
  1565. pInBuffer : ptr to the input buffer passed to netbt
  1566. InBufLen : size of the input buffer
  1567. Return Value:
  1568. None
  1569. --*/
  1570. NTSTATUS
  1571. DeviceIoCtrl(
  1572. HANDLE LanaNumber,
  1573. PVOID pOutBuffer,
  1574. ULONG OutBufLen,
  1575. ULONG Ioctl,
  1576. PVOID pInBuffer,
  1577. ULONG InBufLen
  1578. )
  1579. {
  1580. USHORT usIoctl;
  1581. USHORT usOutBufLen;
  1582. DWORD ActualInBufLen;
  1583. PCHAR pBufferData, pInBufferCopy;
  1584. NTSTATUS status = STATUS_SUCCESS;
  1585. tNBT_IOCTL_HEADER *pIoctlHeader;
  1586. DWORD BytesOut = 0;
  1587. usOutBufLen = (USHORT)OutBufLen;
  1588. usIoctl = (USHORT)Ioctl;
  1589. //
  1590. // vxd will copy the return code in the first 4 bytes of input buffer
  1591. // to make sure we don't trash the input buffer that we received even
  1592. // though it's probably not important, or to provide an input buffer
  1593. // if we weren't given one, we allocate new memory and copy into it
  1594. //
  1595. if (InBufLen < sizeof(NTSTATUS))
  1596. {
  1597. ActualInBufLen = (USHORT) (FIELD_OFFSET (tNBT_IOCTL_HEADER, UserData) + sizeof (NTSTATUS));
  1598. }
  1599. else
  1600. {
  1601. ActualInBufLen = (USHORT) (FIELD_OFFSET (tNBT_IOCTL_HEADER, UserData) + InBufLen);
  1602. }
  1603. if (!(pInBufferCopy = malloc (ActualInBufLen)))
  1604. {
  1605. return (STATUS_INSUFFICIENT_RESOURCES);
  1606. }
  1607. if (((LONG) LanaNumber) >= 0)
  1608. {
  1609. pIoctlHeader = (tNBT_IOCTL_HEADER *) pInBufferCopy;
  1610. pIoctlHeader->Signature = NBT_VERIFY_VXD_IOCTL;
  1611. pIoctlHeader->LanaNumber = (ULONG) LanaNumber;
  1612. pBufferData = (PCHAR) &pIoctlHeader->UserData;
  1613. }
  1614. else
  1615. {
  1616. pBufferData = pInBufferCopy;
  1617. }
  1618. RtlMoveMemory (pBufferData, pInBuffer, (USHORT) InBufLen);
  1619. if (DeviceIoControl (gNbtVxdHandle,
  1620. Ioctl,
  1621. pInBufferCopy,
  1622. ActualInBufLen,
  1623. pOutBuffer,
  1624. OutBufLen,
  1625. &BytesOut,
  1626. FALSE))
  1627. {
  1628. status = STATUS_SUCCESS;
  1629. }
  1630. else
  1631. {
  1632. status = GetLastError();
  1633. //
  1634. // Since VNbt could return Tdi error status, remap it
  1635. //
  1636. if (status == TDI_BUFFER_OVERFLOW)
  1637. {
  1638. status = STATUS_BUFFER_OVERFLOW;
  1639. }
  1640. }
  1641. free (pInBufferCopy);
  1642. return( status );
  1643. }
  1644. //------------------------------------------------------------------------
  1645. /*++
  1646. Routine Description:
  1647. This procedure converts to KBytes or Mbytes
  1648. Arguments:
  1649. Return Value:
  1650. 0 if successful, -1 otherwise.
  1651. --*/
  1652. VOID
  1653. PrintKorM(
  1654. IN PVOID pBytesIn
  1655. )
  1656. {
  1657. ULONG BytesIn = *(ULONG UNALIGNED *) pBytesIn;
  1658. ULONG Bytes;
  1659. if ( BytesIn > 1000 )
  1660. {
  1661. Bytes = BytesIn/1000;
  1662. if ( Bytes > 1000 )
  1663. {
  1664. Bytes = Bytes/1000;
  1665. if (Bytes > 1000 )
  1666. {
  1667. Bytes = Bytes/1000;
  1668. nls_printf("%6dGB ",Bytes);
  1669. }
  1670. else
  1671. {
  1672. nls_printf("%6dMB ",Bytes);
  1673. }
  1674. }
  1675. else
  1676. {
  1677. nls_printf("%6dKB ",Bytes);
  1678. }
  1679. }
  1680. else
  1681. {
  1682. nls_printf("%6dB ",BytesIn);
  1683. }
  1684. }
  1685. #endif // !CHICAGO_PRODUCT