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.

4711 lines
130 KiB

  1. #include <nt.h>
  2. #include <ntrtl.h>
  3. #include <nturtl.h>
  4. #include <windows.h>
  5. #include <lm.h>
  6. #include <ntddbrow.h>
  7. #include <brcommon.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <hostannc.h>
  12. #include <lmbrowsr.h>
  13. #include <nb30.h>
  14. #include <rap.h>
  15. #include <rxserver.h>
  16. #include <srvann.h>
  17. #include <time.h>
  18. #include <tstring.h>
  19. #include <netlib.h>
  20. #include <icanon.h>
  21. #include "..\server\brwins.h"
  22. static char ProgramName[MAX_PATH+1] ;
  23. struct {
  24. LPSTR SwitchName;
  25. LPSTR ShortName;
  26. ULONG SwitchValue;
  27. LPSTR SwitchInformation;
  28. int MinArgc;
  29. int MaxArgc;
  30. LPSTR Syntax;
  31. } CommandSwitchList[] = {
  32. { "ELECT", "EL", BROWSER_DEBUG_ELECT,
  33. "Force election on remote domain",
  34. 4, 5, "<Transport> <Domain> [<EmulatedDomain>]" },
  35. { "GETBLIST", "GB", BROWSER_DEBUG_GET_BACKUP_LIST,
  36. "Get backup list for domain",
  37. 3, 5, "<Transport> [[<Domain>] REFRESH]" },
  38. { "GETMASTER", "GM", BROWSER_DEBUG_GET_MASTER,
  39. "Get remote Master Browser name (using NetBIOS)",
  40. 4, 4, "<Transport> <Domain>" },
  41. { "GETPDC", "GP", BROWSER_DEBUG_GETPDC,
  42. "Get PDC name (using NetBIOS)",
  43. 4, 4, "<Transport> <Domain>" },
  44. { "LISTWFW", "WFW", BROWSER_DEBUG_LIST_WFW,
  45. "List WFW servers that are actually running browser",
  46. 3, 3, "<Domain>" },
  47. { "STATS", "STS", BROWSER_DEBUG_STATISTICS,
  48. "Dump browser statistics",
  49. 2, 4, "[\\\\<Computer> [RESET]]" },
  50. { "STATUS", "STA", BROWSER_DEBUG_STATUS,
  51. "Display status about a domain",
  52. 2, 4, "[-V] [<Domain>]" },
  53. { "TICKLE", "TIC", BROWSER_DEBUG_TICKLE,
  54. "Force remote master to stop",
  55. 4, 5, "<Transport> <Domain> | \\\\<Server> [<EmulatedDomain>]" },
  56. { "VIEW", "VW", BROWSER_DEBUG_VIEW,
  57. "Remote NetServerEnum to a server or domain on transport",
  58. #ifndef _PSS_RELEASE
  59. 3, 7, "Transport [<Domain>|\\\\<Server> [<Flags>|/DOMAIN [<DomainToQuery> [Forever]]]]" },
  60. #else
  61. 3, 6, "Transport [<Domain>|\\\\<Server> [<Flags>|/DOMAIN [<DomainToQuery>]]]" },
  62. #endif
  63. { "DUMPNET", "DN", BROWSER_DEBUG_DUMP_NETWORKS,
  64. "Display the list of transports bound to browser",
  65. 2, 2, "" },
  66. //
  67. // NOTE: Any Option below and including "BREAK" will not be displayed
  68. // with _PSS_RELEASE Defined
  69. //
  70. { "BREAK", "BRK", BROWSER_DEBUG_BREAK_POINT,
  71. "Break into debugger in browser service",
  72. 2, 2, "" },
  73. { "RPCLIST", "RPC", BROWSER_DEBUG_RPCLIST,
  74. "Retrieve the remote server list using RPC",
  75. 3, 6, "<Transport> [<Domain> || \\\\<Server>] [ServerFlags] [GoForever]" },
  76. { "MASTERNAME", "MN", BROWSER_DEBUG_ADD_MASTERNAME,
  77. "Add the <Domain>[1D] Netbios unique name for a transport",
  78. 4, 5, "<Transport> <Domain> [PAUSE]" },
  79. { "WKSTADOM", "WD", BROWSER_DEBUG_ADD_DOMAINNAME,
  80. "Add the <Domain>[00] Netbios unique name for a transport",
  81. 4, 5, "<Transport> <Domain> [PAUSE]" },
  82. { "ENABLE", "EN", BROWSER_DEBUG_ENABLE_BROWSER,
  83. "Enable the browser service",
  84. 2, 2, "" },
  85. { "DEBUG", "DBG", BROWSER_DEBUG_SET_DEBUG,
  86. "Change browser service debug options",
  87. 3, 4, "[[+-]DebugFlag|<Value>] [\\\\<Computer>]" },
  88. { "FINDMASTER", "FM", BROWSER_DEBUG_FIND_MASTER,
  89. "Find master of current domain",
  90. 3, 4, "<Transport> [<EmulatedDomain>]" },
  91. { "MASTERANNOUNCE", "MA", BROWSER_DEBUG_ANNOUNCE_MASTER,
  92. "Send a master announcement with this machine as master",
  93. 4, 5, "<Transport> <Master> [<EmulatedDomain>]" },
  94. { "ILLEGAL", "ILL", BROWSER_DEBUG_ILLEGAL_DGRAM,
  95. "Send an illegal datagram to workstation",
  96. 4, 5, "<Transport> <Computer> [<EmulatedDomain>]" },
  97. { "FORCEANNOUNCE", "FA", BROWSER_DEBUG_FORCE_ANNOUNCE,
  98. "Force all browsers in domain to announce to master browser",
  99. 4, 5, "<Transport> <Domain> [<EmulatedDomain>]" },
  100. { "LOCALLIST", "LL", BROWSER_DEBUG_LOCAL_BRLIST,
  101. "Retrieve the local browser list",
  102. 3, 5, "<Transport> [<ServerFlags>] [<EmulatedDomain>]" },
  103. { "ANNOUNCE", "ANN", BROWSER_DEBUG_ANNOUNCE,
  104. "Send server announcement w/this machine member of domain",
  105. 4, 6, "<Transport> <Domain> [<EmulatedDomainName>] [ASMASTER]" },
  106. { "RPCCMP", "RC", BROWSER_DEBUG_RPCCMP,
  107. "Compare the RPC generated list with the Rx list",
  108. 3, 6, "<Transport> [<Domain> || \\\\<Server>] [<ServerFlags>] [GoForever]" },
  109. { "TRUNCLOG", "TLG", BROWSER_DEBUG_TRUNCATE_LOG,
  110. "Truncate the browser log",
  111. 2, 2, "" },
  112. { "BOWDEBUG", "SD", BROWSER_DEBUG_BOWSERDEBUG,
  113. "Set debug info in the bowser",
  114. 3, 4, "TRUNCATE" },
  115. { "POPSERVER", "PS", BROWSER_DEBUG_POPULATE_SERVER,
  116. "Populate a workgroup with random server names",
  117. 5, 7, "<Transport> <Domain> <NumberOfMachines> [<EmulatedDomain>] [AnnouncementFrequency]" },
  118. { "POPDOMAIN", "PD", BROWSER_DEBUG_POPULATE_DOMAIN,
  119. "Populate a workgroup with random domain names",
  120. 5, 7, "<Transport> <Domain> <NumberOfMachines> [<EmulatedDomain>] [AnnouncementFrequency]" },
  121. { "OTHERDOMAIN", "OTH", BROWSER_DEBUG_GET_OTHLIST,
  122. "Retrieve list of otherdomains that computer listens to",
  123. 3, 3, "<Computer>" },
  124. { "GETWINS", "GW", BROWSER_DEBUG_GET_WINSSERVER,
  125. "Retrieve the primary and backup WINS server",
  126. 3, 3, "<Transport>" },
  127. { "GETDOMAIN", "GWD", BROWSER_DEBUG_GET_DOMAINLIST,
  128. "Retrieve the domain list from a WINS server",
  129. 3, 3, "<Ip Address>" },
  130. { "GETNETBIOS", "GN", BROWSER_DEBUG_GET_NETBIOSNAMES,
  131. "Get Netbios names for a transport",
  132. 3, 4, "<Transport> [<EmulatedDomain>]" },
  133. { "ADDALTCOMP", "AAC", BROWSER_DEBUG_ADD_ALTERNATE,
  134. "Add an alternate computer name",
  135. 4, 5, "<Transport> <AlternateComptureName> [<EmulatedDomain>]" },
  136. { "BIND", "BND", BROWSER_DEBUG_BIND_TRANSPORT,
  137. "Bind a transport to the bowser",
  138. 5, 5, "<Transport> <EmulatedDomain> <AlternateComputenanme>" },
  139. { "UNBIND", "UNB", BROWSER_DEBUG_UNBIND_TRANSPORT,
  140. "Unbind a transport from the bowser",
  141. 3, 4, "<Transport> [<EmulatedDomain>]" },
  142. { "EMULATEDOMAIN", "ED", BROWSER_DEBUG_SET_EMULATEDDOMAIN,
  143. "Create/Set/Delete emulated domain",
  144. 4, 5, "<EmulatedDomain> PDC|BDC|DELETE [<EmulatedComputerName>]" },
  145. { "EMULATEDOMAINENUM", "EDE", BROWSER_DEBUG_SET_EMULATEDDOMAINENUM,
  146. "Enumerate emulated domains",
  147. 2, 2, "" },
  148. { "RENAME", "REN", BROWSER_DEBUG_RENAME_DOMAIN,
  149. "Rename the primary domain or an emulated domain",
  150. 4, 5, "<OldDomainName> <NewDomainName> [VALIDATE_ONLY]" },
  151. { NULL, NULL, 0, NULL }
  152. };
  153. struct {
  154. LPSTR SwitchName;
  155. ULONG SwitchValue;
  156. } DebugSwitchList[] = {
  157. { "INIT", BR_INIT },
  158. { "CRITICAL", BR_CRITICAL },
  159. { "ENUM", BR_SERVER_ENUM },
  160. { "UTIL", BR_UTIL },
  161. { "CONFIG", BR_CONFIG },
  162. { "MAIN", BR_MAIN },
  163. { "BACKUP", BR_BACKUP },
  164. { "MASTER", BR_MASTER },
  165. { "DOMAIN", BR_DOMAIN },
  166. { "NETWORK", BR_NETWORK },
  167. { "CLIENT_OP", BR_CLIENT_OP},
  168. { "TIMER", BR_TIMER },
  169. { "QUEUE", BR_QUEUE },
  170. { "LOCKS", BR_LOCKS },
  171. { "COMMON", BR_COMMON },
  172. { "ALL", BR_ALL },
  173. { NULL, 0 }
  174. };
  175. typedef struct _BIT_NAME {
  176. DWORD dwValue ;
  177. LPSTR lpString ;
  178. LPSTR Comment;
  179. } BIT_NAME ;
  180. BIT_NAME BitToStringTable[] = {
  181. { SV_TYPE_WORKSTATION, "W", "Workstation" },
  182. { SV_TYPE_SERVER, "S", "Server" },
  183. { SV_TYPE_SQLSERVER, "SQL", "SQLServer" } ,
  184. { SV_TYPE_DOMAIN_CTRL, "PDC", "PrimaryDomainController" } ,
  185. { SV_TYPE_DOMAIN_BAKCTRL, "BDC", "BackupDomainController" } ,
  186. { SV_TYPE_TIME_SOURCE, "TS", "TimeSource" } ,
  187. { SV_TYPE_AFP, "AFP", "AFPServer" } ,
  188. { SV_TYPE_NOVELL, "NV", "Novell" } ,
  189. { SV_TYPE_DOMAIN_MEMBER, "MBC", "MemberServer" } ,
  190. { SV_TYPE_PRINTQ_SERVER, "PQ", "PrintServer" } ,
  191. { SV_TYPE_DIALIN_SERVER, "DL", "DialinServer" } ,
  192. { SV_TYPE_XENIX_SERVER, "XN", "Xenix" } ,
  193. { SV_TYPE_NT, "NT", "Windows NT" } ,
  194. { SV_TYPE_WFW, "WFW", "WindowsForWorkgroups" } ,
  195. { SV_TYPE_SERVER_MFPN, "MFPN", "MS Netware" } ,
  196. { SV_TYPE_SERVER_NT, "SS", "StandardServer" } ,
  197. { SV_TYPE_POTENTIAL_BROWSER, "PBR", "PotentialBrowser" } ,
  198. { SV_TYPE_BACKUP_BROWSER, "BBR", "BackupBrowser" } ,
  199. { SV_TYPE_MASTER_BROWSER, "MBR", "MasterBrowser" } ,
  200. // { SV_TYPE_DOMAIN_MASTER, "DMB", "DomainMasterBrowser" } ,
  201. { SV_TYPE_SERVER_OSF, "OSF", "OSFServer" } ,
  202. { SV_TYPE_SERVER_VMS, "VMS", "VMSServer" } ,
  203. { SV_TYPE_WINDOWS, "W95", "Windows95" } ,
  204. { SV_TYPE_DFS, "DFS", "DistributedFileSystem" } ,
  205. { SV_TYPE_CLUSTER_NT, "CLUS", "NTCluster" },
  206. { SV_TYPE_DCE, "DCE", "IBM DSS" },
  207. { 0, "", NULL }
  208. } ;
  209. #include <bowdbg.h>
  210. #ifdef notdef
  211. struct {
  212. LPSTR SwitchName;
  213. ULONG SwitchValue;
  214. } BowserSwitchList[] = {
  215. { "DOMAIN", DPRT_DOMAIN },
  216. { "ANNOUNCE", DPRT_ANNOUNCE },
  217. { "TDI", DPRT_TDI },
  218. { "FSPDISP", DPRT_FSPDISP },
  219. { "BROWSER", DPRT_BROWSER },
  220. { "ELECT", DPRT_ELECT },
  221. { "CLIENT", DPRT_CLIENT },
  222. { "MASTER", DPRT_MASTER },
  223. { "SRVENUM", DPRT_SRVENUM },
  224. { "NETLOGON", DPRT_NETLOGON },
  225. { "FSCTL", DPRT_FSCTL },
  226. { "INIT", DPRT_INIT },
  227. { "REF", DPRT_REF },
  228. { "SCAVTHRD", DPRT_SCAVTHRD },
  229. { "TIMER", DPRT_TIMER },
  230. { "PACK", DPRT_PACK },
  231. { "ALL", 0xffffffff },
  232. { NULL, 0 }
  233. };
  234. #endif // notdef
  235. //
  236. // forward declarations
  237. //
  238. NET_API_STATUS
  239. GetBrowserTransportList(
  240. OUT PLMDR_TRANSPORT_LIST *TransportList
  241. );
  242. VOID
  243. BrowserStatus(
  244. IN BOOL Verbose,
  245. OUT PCHAR Domain OPTIONAL
  246. );
  247. NET_API_STATUS
  248. GetMasterServerNames(
  249. IN PUNICODE_STRING NetworkName,
  250. IN PUNICODE_STRING EmulatedDomainName,
  251. OUT LPWSTR *MasterName
  252. );
  253. PCHAR
  254. UnicodeToPrintfString(
  255. PWCHAR WideChar
  256. );
  257. PCHAR
  258. UnicodeToPrintfString2(
  259. PWCHAR WideChar
  260. );
  261. NET_API_STATUS
  262. GetLocalBrowseList(
  263. IN PUNICODE_STRING Network,
  264. IN PUNICODE_STRING EmulatedDomainName,
  265. IN ULONG Level,
  266. IN ULONG ServerType,
  267. OUT PVOID *ServerList,
  268. OUT PULONG EntriesRead,
  269. OUT PULONG TotalEntries
  270. );
  271. VOID
  272. View(
  273. IN PCHAR Transport,
  274. IN PCHAR ServerOrDomain,
  275. IN PCHAR Flags,
  276. IN PCHAR Domain,
  277. IN BOOL GoForever
  278. );
  279. VOID
  280. ListWFW(
  281. IN PCHAR Domain
  282. );
  283. VOID
  284. RpcList(
  285. IN PCHAR Transport,
  286. IN PCHAR ServerOrDomain,
  287. IN PCHAR Flags,
  288. IN BOOL GoForever
  289. );
  290. VOID
  291. RpcCmp(
  292. IN PCHAR Transport,
  293. IN PCHAR ServerOrDomain,
  294. IN PCHAR Flags,
  295. IN BOOL GoForever
  296. );
  297. VOID
  298. GetLocalList(
  299. IN PCHAR Transport,
  300. IN PCHAR FlagsString,
  301. IN PCHAR EmulatedDomain
  302. );
  303. VOID
  304. PrintNetbiosNames(
  305. IN PCHAR Transport,
  306. IN PCHAR EmulatedDomain OPTIONAL
  307. );
  308. NET_API_STATUS
  309. GetNetbiosNames(
  310. IN PUNICODE_STRING Network,
  311. IN PUNICODE_STRING EmulatedDomainName,
  312. OUT PVOID *NameList,
  313. OUT PULONG EntriesRead,
  314. OUT PULONG TotalEntries
  315. );
  316. NET_API_STATUS
  317. AddAlternateComputerName(
  318. IN PCHAR Transport,
  319. IN PCHAR ComputerName,
  320. IN PCHAR EmulatedDomain
  321. );
  322. NET_API_STATUS
  323. BindTransport(
  324. IN BOOL IsBind,
  325. IN PCHAR Transport,
  326. IN PCHAR EmulatedDomain,
  327. IN PCHAR ComputerName
  328. );
  329. VOID
  330. DumpTransportList(
  331. VOID
  332. );
  333. VOID
  334. GetOtherdomains(
  335. IN PCHAR ServerName
  336. );
  337. VOID
  338. IllegalDatagram(
  339. IN PCHAR Transport,
  340. IN PCHAR ServerName,
  341. IN PCHAR EmulatedDomain
  342. );
  343. VOID
  344. AnnounceMaster(
  345. IN PCHAR Transport,
  346. IN PCHAR ServerName,
  347. IN PCHAR EmulatedDomain
  348. );
  349. VOID
  350. Announce(
  351. IN PCHAR Transport,
  352. IN PCHAR Domain,
  353. IN PCHAR EmulatedDomain,
  354. IN BOOL AsMaster
  355. );
  356. VOID
  357. Populate(
  358. IN BOOL PopulateDomains,
  359. IN PCHAR Transport,
  360. IN PCHAR Domain,
  361. IN PCHAR EmulatedDomain,
  362. IN PCHAR NumberOfMachinesString,
  363. IN PCHAR PeriodicityString OPTIONAL
  364. );
  365. VOID
  366. AddMasterName(
  367. IN PCHAR Transport,
  368. IN PCHAR Domain,
  369. IN BOOL Pause
  370. );
  371. VOID
  372. AddDomainName(
  373. IN PCHAR Transport,
  374. IN PCHAR Domain,
  375. IN BOOL Pause
  376. );
  377. VOID
  378. GetMaster(
  379. IN PCHAR Transport,
  380. IN PCHAR Domain
  381. );
  382. VOID
  383. GetPdc(
  384. IN PCHAR Transport,
  385. IN PCHAR Domain
  386. );
  387. VOID
  388. FindMaster(
  389. IN PCHAR Transport,
  390. IN PCHAR EmulatedDomain
  391. );
  392. VOID
  393. Elect(
  394. IN PCHAR Transport,
  395. IN PCHAR Domain,
  396. IN PCHAR EmulatedDomain
  397. );
  398. VOID
  399. Tickle(
  400. IN PCHAR Transport,
  401. IN PCHAR Domain,
  402. IN PCHAR EmulatedDomain
  403. );
  404. VOID
  405. ForceAnnounce(
  406. IN PCHAR Transport,
  407. IN PCHAR Domain,
  408. IN PCHAR EmulatedDomain
  409. );
  410. VOID
  411. GetBlist(
  412. IN PCHAR TransportName,
  413. IN PCHAR DomainName,
  414. IN BOOLEAN ForceRescan
  415. );
  416. NET_API_STATUS
  417. EnableService(
  418. IN LPTSTR ServiceName
  419. );
  420. VOID
  421. DumpStatistics(
  422. IN ULONG NArgs,
  423. IN PCHAR Arg1
  424. );
  425. VOID
  426. TruncateBowserLog();
  427. VOID
  428. CloseBowserLog();
  429. VOID
  430. OpenBowserLog(PCHAR FileName);
  431. VOID
  432. SetBowserDebug(PCHAR DebugBits);
  433. VOID
  434. usage( char *details ) ;
  435. VOID
  436. help( char *details ) ;
  437. BOOL
  438. look_for_help(int argc, char **argv) ;
  439. VOID
  440. qualify_transport(CHAR *old_name, PUNICODE_STRING new_name, BOOL AllowNonExistent );
  441. VOID
  442. DisplayServerInfo101(
  443. PSERVER_INFO_101 Server,
  444. BOOL DomainEnumeration
  445. );
  446. DWORD
  447. display_sv_bits(DWORD dwBits) ;
  448. CHAR *
  449. get_error_text(DWORD dwErr) ;
  450. VOID
  451. GetWinsServer(
  452. IN PCHAR Transport
  453. );
  454. VOID
  455. GetDomainList(
  456. IN PCHAR IpAddress
  457. );
  458. VOID
  459. SetEmulatedDomain(
  460. IN PCHAR EmulatedDomain,
  461. IN PCHAR Role,
  462. IN PCHAR EmulatedComputer
  463. );
  464. VOID
  465. EnumEmulatedDomains(
  466. );
  467. //
  468. // functions
  469. //
  470. VOID
  471. usage(
  472. char *details
  473. )
  474. {
  475. ULONG i = 0;
  476. DWORD LineLength;
  477. #ifndef _PSS_RELEASE
  478. printf("Usage: %s Command [Options]\n", ProgramName);
  479. #else
  480. printf("Usage: %s Command [Options | /HELP]\n", ProgramName);
  481. #endif
  482. printf("Where <Command> is one of:\n\n");
  483. #ifndef _PSS_RELEASE
  484. while (CommandSwitchList[i].SwitchName != NULL)
  485. #else
  486. while (CommandSwitchList[i].SwitchValue != BROWSER_DEBUG_BREAK_POINT )
  487. #endif
  488. {
  489. printf(" %-14.14s(%3.3s) - %s\n",
  490. CommandSwitchList[i].SwitchName,
  491. CommandSwitchList[i].ShortName,
  492. CommandSwitchList[i].SwitchInformation);
  493. i += 1;
  494. }
  495. if (details)
  496. printf("%s", details);
  497. //
  498. // Print the descriptions of server type bits
  499. //
  500. printf("\nIn server (or domain) list displays, the following flags are used:\n");
  501. LineLength = 0;
  502. i=0;
  503. while ( BitToStringTable[i].dwValue != 0 ) {
  504. DWORD ItemLength;
  505. ItemLength = strlen(BitToStringTable[i].lpString) +
  506. 1 +
  507. strlen(BitToStringTable[i].Comment);
  508. if ( LineLength + ItemLength >= 77 ) {
  509. LineLength = 0;
  510. printf(",\n");
  511. }
  512. if ( LineLength == 0) {
  513. printf(" ");
  514. LineLength = 5;
  515. } else {
  516. printf(", ");
  517. LineLength += 2;
  518. }
  519. printf( "%s=%s", BitToStringTable[i].lpString, BitToStringTable[i].Comment);
  520. LineLength += ItemLength;
  521. i++;
  522. }
  523. printf("\n");
  524. }
  525. VOID
  526. CommandUsage(
  527. ULONG ControlCode
  528. )
  529. /*++
  530. Routine Description:
  531. Print the usage description for a single command
  532. Arguments:
  533. ControlCode - Control code of the command who's usage is to be printed.
  534. Return Value:
  535. None
  536. --*/
  537. {
  538. ULONG Index;
  539. ULONG i;
  540. //
  541. // Look up the command in the list of commands.
  542. //
  543. Index = 0;
  544. while (CommandSwitchList[Index].SwitchName != NULL) {
  545. if ( ControlCode == CommandSwitchList[Index].SwitchValue ) {
  546. break;
  547. }
  548. Index += 1;
  549. }
  550. if (CommandSwitchList[Index].SwitchName == NULL) {
  551. usage("Unknown switch specified");
  552. return;
  553. }
  554. //
  555. // Print command usage.
  556. //
  557. printf( "Usage: %s %s %s\n",
  558. ProgramName,
  559. CommandSwitchList[Index].SwitchName,
  560. CommandSwitchList[Index].Syntax );
  561. //
  562. // Print additional command specific information.
  563. //
  564. switch (ControlCode) {
  565. case BROWSER_DEBUG_VIEW:
  566. printf(" %s VIEW <transport>\n"
  567. " %s VIEW <transport> <domain>|\\\\<Server> [/DOMAIN]\n"
  568. " %s VIEW <transport> <server> /DOMAIN <domain>\n",
  569. ProgramName,
  570. ProgramName,
  571. ProgramName );
  572. break;
  573. case BROWSER_DEBUG_SET_DEBUG:
  574. printf("where DebugFlag is one of the following:\n");
  575. i = 0;
  576. while (DebugSwitchList[i].SwitchName != NULL) {
  577. printf("\t%s\n", DebugSwitchList[i].SwitchName);
  578. i += 1;
  579. }
  580. break;
  581. case BROWSER_DEBUG_BOWSERDEBUG:
  582. printf(" %s BOWDEBUG CLOSE\n"
  583. " %s BOWDEBUG OPEN <FileName>\n"
  584. " %s BOWDEBUG DEBUG <Flags>\n",
  585. ProgramName,
  586. ProgramName,
  587. ProgramName );
  588. #ifdef notdef
  589. printf("where Flags is one of the following:\n");
  590. i = 0;
  591. while (BowserSwitchList[i].SwitchName != NULL) {
  592. printf("\t%s\n", BowserSwitchList[i].SwitchName);
  593. i += 1;
  594. }
  595. #endif // notdef
  596. break;
  597. }
  598. printf( "%s.\n",
  599. CommandSwitchList[Index].SwitchInformation );
  600. help("");
  601. exit(4);
  602. }
  603. VOID
  604. help(
  605. char *details
  606. )
  607. {
  608. printf("%s\nType \"%s\" to list all switches.\n", details, ProgramName);
  609. }
  610. VOID
  611. qualify_transport(CHAR *old_name, PUNICODE_STRING new_name, BOOL AllowNonExistent )
  612. {
  613. int len = strlen(old_name) ;
  614. char *devicestring = "\\device\\" ;
  615. int devicelen = strlen(devicestring) ;
  616. CHAR QualifiedTransport[MAX_PATH] ;
  617. ANSI_STRING AString;
  618. ULONG TransportIndex;
  619. NET_API_STATUS Status;
  620. PLMDR_TRANSPORT_LIST TransportList, TransportEntry;
  621. //
  622. // Get a list of all the transports supported by the browser.
  623. //
  624. Status = GetBrowserTransportList(&TransportList);
  625. if (Status != NERR_Success) {
  626. printf("Unable to retrieve transport list: %s\n", get_error_text(Status));
  627. exit(Status);
  628. }
  629. //
  630. // Handle a transport number
  631. //
  632. if ( (TransportIndex = strtoul(old_name, NULL, 0)) != 0 ) {
  633. ULONG TransportNumber = 0;
  634. TransportEntry = TransportList;
  635. while (TransportEntry != NULL) {
  636. UNICODE_STRING TransportName;
  637. TransportName.Buffer = TransportEntry->TransportName;
  638. TransportName.Length = (USHORT)TransportEntry->TransportNameLength;
  639. TransportName.MaximumLength = (USHORT)TransportEntry->TransportNameLength;
  640. TransportNumber ++;
  641. //
  642. // If we've reached the right transport,
  643. // return the transport name to the caller.
  644. //
  645. if ( TransportNumber == TransportIndex ) {
  646. if (!RtlCreateUnicodeString( new_name, TransportEntry->TransportName )){
  647. printf("Error: Failed to create string (out of memory?)\n");
  648. exit(1);
  649. }
  650. // we have a valid transport
  651. return;
  652. }
  653. if (TransportEntry->NextEntryOffset == 0) {
  654. TransportEntry = NULL;
  655. } else {
  656. TransportEntry = (PLMDR_TRANSPORT_LIST)((PCHAR)TransportEntry+TransportEntry->NextEntryOffset);
  657. }
  658. }
  659. printf("Browser only has %ld transports and you asked for transport %s\n", TransportNumber, old_name );
  660. //
  661. // Handle a transport name.
  662. //
  663. } else {
  664. // Handle transport not preceeded by \device\.
  665. if (_strnicmp(old_name, devicestring, devicelen) != 0) {
  666. strcpy(QualifiedTransport, devicestring) ;
  667. strcat(QualifiedTransport, (*old_name == '\\') ? old_name+1 : old_name) ;
  668. // Handle all other transport values.
  669. } else {
  670. strcpy(QualifiedTransport, old_name) ;
  671. }
  672. //
  673. // Convert it to a UNICODE_STRING
  674. //
  675. RtlInitString(&AString, QualifiedTransport);
  676. Status = RtlAnsiStringToUnicodeString(new_name, &AString, TRUE);
  677. if (ERROR_SUCCESS != Status) {
  678. printf("Error: Failed to create string (out of memory?)\n");
  679. exit(1);
  680. }
  681. //
  682. // Ensure the specified transport is on the list of supported transports.
  683. //
  684. TransportEntry = TransportList;
  685. while (TransportEntry != NULL) {
  686. UNICODE_STRING TransportName;
  687. TransportName.Buffer = TransportEntry->TransportName;
  688. TransportName.Length = (USHORT)TransportEntry->TransportNameLength;
  689. TransportName.MaximumLength = (USHORT)TransportEntry->TransportNameLength;
  690. //
  691. // If we've reached the right transport,
  692. // return the transport name to the caller.
  693. //
  694. if ( RtlEqualUnicodeString( new_name, &TransportName, TRUE ) ) {
  695. return;
  696. }
  697. if (TransportEntry->NextEntryOffset == 0) {
  698. TransportEntry = NULL;
  699. } else {
  700. TransportEntry = (PLMDR_TRANSPORT_LIST)((PCHAR)TransportEntry+TransportEntry->NextEntryOffset);
  701. }
  702. }
  703. if (AllowNonExistent) {
  704. return;
  705. }
  706. printf("The browser is not bound to transport %s\n", old_name );
  707. }
  708. //
  709. // The transport specified was invalid. Display the list of
  710. // valid transports.
  711. //
  712. DumpTransportList();
  713. printf("\n%s accepts any of the following forms for transport name:\n", ProgramName );
  714. printf(" 1, \\device\\XXX, XXX\n\n" );
  715. exit(0);
  716. }
  717. NET_API_STATUS
  718. EnableService(
  719. IN LPTSTR ServiceName
  720. )
  721. {
  722. SC_HANDLE ServiceControllerHandle;
  723. SC_HANDLE ServiceHandle;
  724. ServiceControllerHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
  725. if (ServiceControllerHandle == NULL) {
  726. return GetLastError();
  727. }
  728. ServiceHandle = OpenService(ServiceControllerHandle, ServiceName, SERVICE_CHANGE_CONFIG);
  729. if (ServiceHandle == NULL) {
  730. CloseServiceHandle(ServiceControllerHandle);
  731. return GetLastError();
  732. }
  733. if (!ChangeServiceConfig(ServiceHandle, SERVICE_NO_CHANGE,
  734. SERVICE_DEMAND_START,
  735. SERVICE_NO_CHANGE,
  736. NULL,
  737. NULL,
  738. NULL,
  739. NULL,
  740. NULL,
  741. NULL,
  742. NULL)) {
  743. CloseServiceHandle(ServiceHandle);
  744. CloseServiceHandle(ServiceControllerHandle);
  745. return GetLastError();
  746. }
  747. CloseServiceHandle(ServiceHandle);
  748. CloseServiceHandle(ServiceControllerHandle);
  749. return NERR_Success;
  750. }
  751. VOID
  752. GetBlist(
  753. IN PCHAR TransportName,
  754. IN PCHAR DomainName,
  755. IN BOOLEAN ForceRescan
  756. )
  757. {
  758. NET_API_STATUS Status;
  759. UNICODE_STRING UTransportName;
  760. LPTSTR Domain;
  761. PWSTR *BrowserList;
  762. ULONG BrowserListLength;
  763. ULONG i;
  764. qualify_transport(TransportName, &UTransportName, FALSE ) ;
  765. Domain = NULL;
  766. if (DomainName != NULL) {
  767. UNICODE_STRING UDomainName;
  768. ANSI_STRING ADomainName;
  769. RtlInitString(&ADomainName, DomainName);
  770. RtlAnsiStringToUnicodeString(&UDomainName, &ADomainName, TRUE);
  771. Domain = UDomainName.Buffer;
  772. }
  773. Status = GetBrowserServerList(&UTransportName, Domain,
  774. &BrowserList,
  775. &BrowserListLength,
  776. ForceRescan);
  777. if (Status != NERR_Success) {
  778. printf("Unable to get backup list: %s\n", get_error_text(Status));
  779. exit(1);
  780. }
  781. for (i = 0; i < BrowserListLength ; i ++ ) {
  782. printf("Browser: %s\n", UnicodeToPrintfString(BrowserList[i]));
  783. }
  784. }
  785. NET_API_STATUS
  786. SendDatagramA(
  787. IN PCHAR Transport,
  788. IN PCHAR EmulatedDomain OPTIONAL,
  789. IN PCHAR NetbiosName,
  790. IN DGRECEIVER_NAME_TYPE NameType,
  791. IN PVOID Buffer,
  792. IN ULONG BufferSize
  793. )
  794. /*++
  795. Routine Description:
  796. Send a datagram on the specified transport.
  797. The arguments are in the OEM character set.
  798. Arguments:
  799. Transport - Transport to send on (might not be qualified yet.)
  800. EmulatedDomain - Emulated Domain name. NULL implies primary domain.
  801. #endif
  802. NetbiosName - Name to send the datagram to. (If Netbios name begins with
  803. leading \\, they are removed.)
  804. NameType - Type of 'Name'
  805. Buffer - data to send
  806. BufferSize - Number of byte in 'Buffer'
  807. Return Value:
  808. NET_API_STATUS - NERR_Success or reason for failure.
  809. --*/
  810. {
  811. NET_API_STATUS NetStatus;
  812. UNICODE_STRING TransportName;
  813. UNICODE_STRING EmulatedDomainName;
  814. ANSI_STRING AEmulatedDomainName;
  815. UNICODE_STRING UNetbiosName;
  816. ANSI_STRING ANetbiosName;
  817. HANDLE BrowserHandle;
  818. //
  819. // Qualify the transport name and convert it to unicode
  820. //
  821. qualify_transport(Transport, &TransportName, FALSE) ;
  822. //
  823. // Convert the emulated domain name to unicode
  824. //
  825. RtlInitString(&AEmulatedDomainName, EmulatedDomain);
  826. RtlAnsiStringToUnicodeString(&EmulatedDomainName, &AEmulatedDomainName, TRUE);
  827. //
  828. // Convert the destination Netbios name to unicode
  829. //
  830. if (NetbiosName[0] == '\\' && NetbiosName[1] == '\\') {
  831. RtlInitString(&ANetbiosName, &NetbiosName[2]);
  832. } else {
  833. RtlInitString(&ANetbiosName, NetbiosName );
  834. }
  835. RtlAnsiStringToUnicodeString(&UNetbiosName, &ANetbiosName, TRUE);
  836. //
  837. // Send the datagram
  838. //
  839. OpenBrowser(&BrowserHandle);
  840. NetStatus = SendDatagram( BrowserHandle,
  841. &TransportName,
  842. &EmulatedDomainName,
  843. UNetbiosName.Buffer,
  844. NameType,
  845. Buffer,
  846. BufferSize );
  847. CloseHandle(BrowserHandle);
  848. return NetStatus;
  849. }
  850. VOID
  851. Elect(
  852. IN PCHAR Transport,
  853. IN PCHAR Domain,
  854. IN PCHAR EmulatedDomain
  855. )
  856. {
  857. REQUEST_ELECTION ElectionRequest;
  858. ElectionRequest.Type = Election;
  859. ElectionRequest.ElectionRequest.Version = 0;
  860. ElectionRequest.ElectionRequest.Criteria = 0;
  861. ElectionRequest.ElectionRequest.TimeUp = 0;
  862. ElectionRequest.ElectionRequest.MustBeZero = 0;
  863. ElectionRequest.ElectionRequest.ServerName[0] = '\0';
  864. SendDatagramA( Transport,
  865. EmulatedDomain,
  866. Domain,
  867. BrowserElection,
  868. &ElectionRequest,
  869. sizeof(ElectionRequest) );
  870. }
  871. VOID
  872. Tickle(
  873. IN PCHAR Transport,
  874. IN PCHAR Domain,
  875. IN PCHAR EmulatedDomain
  876. )
  877. {
  878. RESET_STATE ResetState;
  879. ResetState.Type = ResetBrowserState;
  880. ResetState.ResetStateRequest.Options = RESET_STATE_STOP_MASTER;
  881. SendDatagramA( Transport,
  882. EmulatedDomain,
  883. Domain,
  884. ((Domain[0] == '\\' && Domain[1] == '\\') ?
  885. ComputerName : MasterBrowser),
  886. &ResetState,
  887. sizeof(ResetState));
  888. }
  889. VOID
  890. GetMaster(
  891. IN PCHAR Transport,
  892. IN PCHAR Domain
  893. )
  894. {
  895. NET_API_STATUS Status;
  896. UNICODE_STRING TransportName;
  897. ANSI_STRING AString;
  898. WCHAR MasterName[256];
  899. UNICODE_STRING DomainName;
  900. qualify_transport(Transport, &TransportName, FALSE ) ;
  901. RtlInitString(&AString, Domain);
  902. RtlAnsiStringToUnicodeString(&DomainName, &AString, TRUE);
  903. Status = GetNetBiosMasterName(
  904. TransportName.Buffer,
  905. DomainName.Buffer,
  906. MasterName,
  907. NULL);
  908. if (Status != NERR_Success) {
  909. printf("Unable to get Master: %s\n", get_error_text(Status));
  910. exit(1);
  911. }
  912. printf("Master Browser: %s\n", UnicodeToPrintfString(MasterName));
  913. }
  914. #define SPACES " "
  915. #define ClearNcb( PNCB ) { \
  916. RtlZeroMemory( PNCB , sizeof (NCB) ); \
  917. RtlCopyMemory( (PNCB)->ncb_name, SPACES, sizeof(SPACES)-1 );\
  918. RtlCopyMemory( (PNCB)->ncb_callname, SPACES, sizeof(SPACES)-1 );\
  919. }
  920. VOID
  921. AddMasterName(
  922. IN PCHAR Transport,
  923. IN PCHAR Domain,
  924. IN BOOL Pause
  925. )
  926. {
  927. NET_API_STATUS Status;
  928. UNICODE_STRING TransportName;
  929. CCHAR LanaNum;
  930. NCB AddNameNcb;
  931. qualify_transport(Transport, &TransportName, FALSE) ;
  932. Status = BrGetLanaNumFromNetworkName(TransportName.Buffer, &LanaNum);
  933. if (Status != NERR_Success) {
  934. printf("Unable to get transport: %lx\n", Status);
  935. return;
  936. }
  937. ClearNcb(&AddNameNcb)
  938. AddNameNcb.ncb_command = NCBRESET;
  939. AddNameNcb.ncb_lsn = 0; // Request resources
  940. AddNameNcb.ncb_lana_num = LanaNum;
  941. AddNameNcb.ncb_callname[0] = 0; // 16 sessions
  942. AddNameNcb.ncb_callname[1] = 0; // 16 commands
  943. AddNameNcb.ncb_callname[2] = 0; // 8 names
  944. AddNameNcb.ncb_callname[3] = 0; // Don't want the reserved address
  945. Netbios( &AddNameNcb );
  946. ClearNcb( &AddNameNcb );
  947. //
  948. // Uppercase the remote name.
  949. //
  950. _strupr(Domain);
  951. AddNameNcb.ncb_command = NCBADDNAME;
  952. RtlCopyMemory( AddNameNcb.ncb_name, Domain, strlen(Domain));
  953. AddNameNcb.ncb_name[15] = MASTER_BROWSER_SIGNATURE;
  954. AddNameNcb.ncb_lana_num = LanaNum;
  955. AddNameNcb.ncb_length = 0;
  956. AddNameNcb.ncb_buffer = NULL;
  957. Netbios( &AddNameNcb );
  958. if ( AddNameNcb.ncb_retcode == NRC_GOODRET ) {
  959. printf("Successfully added master name!!!!!\n");
  960. } else {
  961. printf("Unable to add master name: %lx\n", AddNameNcb.ncb_retcode);
  962. }
  963. if (Pause) {
  964. printf("Press any key to continue...");
  965. getchar();
  966. }
  967. }
  968. VOID
  969. AddDomainName(
  970. IN PCHAR Transport,
  971. IN PCHAR Domain,
  972. IN BOOL Pause
  973. )
  974. {
  975. NET_API_STATUS Status;
  976. UNICODE_STRING TransportName;
  977. CCHAR LanaNum;
  978. NCB AddNameNcb;
  979. qualify_transport(Transport, &TransportName, FALSE ) ;
  980. Status = BrGetLanaNumFromNetworkName(TransportName.Buffer, &LanaNum);
  981. if (Status != NERR_Success) {
  982. printf("Unable to get transport: %lx\n", Status);
  983. return;
  984. }
  985. ClearNcb(&AddNameNcb)
  986. AddNameNcb.ncb_command = NCBRESET;
  987. AddNameNcb.ncb_lsn = 0; // Request resources
  988. AddNameNcb.ncb_lana_num = LanaNum;
  989. AddNameNcb.ncb_callname[0] = 0; // 16 sessions
  990. AddNameNcb.ncb_callname[1] = 0; // 16 commands
  991. AddNameNcb.ncb_callname[2] = 0; // 8 names
  992. AddNameNcb.ncb_callname[3] = 0; // Don't want the reserved address
  993. Netbios( &AddNameNcb );
  994. ClearNcb( &AddNameNcb );
  995. //
  996. // Uppercase the remote name.
  997. //
  998. _strupr(Domain);
  999. AddNameNcb.ncb_command = NCBADDNAME;
  1000. RtlCopyMemory( AddNameNcb.ncb_name, Domain, strlen(Domain));
  1001. AddNameNcb.ncb_name[15] = PRIMARY_DOMAIN_SIGNATURE;
  1002. AddNameNcb.ncb_lana_num = LanaNum;
  1003. AddNameNcb.ncb_length = 0;
  1004. AddNameNcb.ncb_buffer = NULL;
  1005. Netbios( &AddNameNcb );
  1006. if ( AddNameNcb.ncb_retcode == NRC_GOODRET ) {
  1007. printf("Successfully added master name!!!!!\n");
  1008. } else {
  1009. printf("Unable to add master name: %lx\n", AddNameNcb.ncb_retcode);
  1010. }
  1011. if (Pause) {
  1012. printf("Press any key to continue...");
  1013. getchar();
  1014. }
  1015. }
  1016. VOID
  1017. FindMaster(
  1018. IN PCHAR Transport,
  1019. IN PCHAR EmulatedDomain
  1020. )
  1021. {
  1022. NET_API_STATUS Status;
  1023. UNICODE_STRING TransportName;
  1024. UNICODE_STRING EmulatedDomainName;
  1025. ANSI_STRING AEmulatedDomainName;
  1026. LPWSTR MasterName;
  1027. qualify_transport(Transport, &TransportName, FALSE) ;
  1028. RtlInitString(&AEmulatedDomainName, EmulatedDomain);
  1029. Status = RtlAnsiStringToUnicodeString(&EmulatedDomainName, &AEmulatedDomainName, TRUE);
  1030. if (ERROR_SUCCESS != Status) {
  1031. printf("Error: Unable to create string (out of memory?)\n");
  1032. exit(1);
  1033. }
  1034. Status = GetMasterServerNames(&TransportName, &EmulatedDomainName, &MasterName);
  1035. if (Status != NERR_Success) {
  1036. printf("Unable to get Master: %s\n", get_error_text(Status));
  1037. exit(1);
  1038. }
  1039. printf("Master Browser: %s\n", UnicodeToPrintfString(MasterName));
  1040. }
  1041. NET_API_STATUS
  1042. GetMasterServerNames(
  1043. IN PUNICODE_STRING NetworkName,
  1044. IN PUNICODE_STRING EmulatedDomainName,
  1045. OUT LPWSTR *MasterName
  1046. )
  1047. /*++
  1048. Routine Description:
  1049. This function is the worker routine called to determine the name of the
  1050. master browser server for a particular network.
  1051. Arguments:
  1052. None.
  1053. Return Value:
  1054. Status - The status of the operation.
  1055. --*/
  1056. {
  1057. NET_API_STATUS Status;
  1058. HANDLE BrowserHandle;
  1059. NET_API_STATUS status = NERR_Success;
  1060. PLMDR_REQUEST_PACKET RequestPacket = NULL;
  1061. RequestPacket = malloc(sizeof(LMDR_REQUEST_PACKET)+MAXIMUM_FILENAME_LENGTH*sizeof(WCHAR));
  1062. if (RequestPacket == NULL) {
  1063. return(ERROR_NOT_ENOUGH_MEMORY);
  1064. }
  1065. Status = OpenBrowser(&BrowserHandle);
  1066. if (Status != NERR_Success) {
  1067. goto cleanup;
  1068. }
  1069. RequestPacket->Version = LMDR_REQUEST_PACKET_VERSION_DOM;
  1070. RequestPacket->TransportName = *NetworkName;
  1071. RequestPacket->EmulatedDomainName = *EmulatedDomainName;
  1072. //
  1073. // Reference the network while the I/O is pending.
  1074. //
  1075. Status = BrDgReceiverIoControl(BrowserHandle,
  1076. IOCTL_LMDR_GET_MASTER_NAME,
  1077. RequestPacket,
  1078. sizeof(LMDR_REQUEST_PACKET)+NetworkName->Length,
  1079. RequestPacket,
  1080. sizeof(LMDR_REQUEST_PACKET)+MAXIMUM_FILENAME_LENGTH*sizeof(WCHAR),
  1081. NULL);
  1082. if (Status != NERR_Success) {
  1083. printf("Browser: Unable to determine master for network %s: %ld\n", UnicodeToPrintfString(NetworkName->Buffer), Status);
  1084. goto cleanup;
  1085. }
  1086. *MasterName = malloc(RequestPacket->Parameters.GetMasterName.MasterNameLength+sizeof(WCHAR));
  1087. if ( *MasterName == NULL ) {
  1088. status = ERROR_NOT_ENOUGH_MEMORY;
  1089. goto cleanup;
  1090. }
  1091. RtlCopyMemory(*MasterName, RequestPacket->Parameters.GetMasterName.Name,
  1092. RequestPacket->Parameters.GetMasterName.MasterNameLength+sizeof(WCHAR));
  1093. cleanup:
  1094. if (RequestPacket) {
  1095. free(RequestPacket);
  1096. }
  1097. return Status;
  1098. }
  1099. VOID
  1100. AnnounceMaster(
  1101. IN PCHAR Transport,
  1102. IN PCHAR ServerName,
  1103. IN PCHAR EmulatedDomain
  1104. )
  1105. {
  1106. CHAR Buffer[sizeof(MASTER_ANNOUNCEMENT)+MAX_COMPUTERNAME_LENGTH+1];
  1107. PMASTER_ANNOUNCEMENT MasterAnnouncementp = (PMASTER_ANNOUNCEMENT)Buffer;
  1108. ULONG ComputerNameSize = MAX_COMPUTERNAME_LENGTH+1;
  1109. //
  1110. // Get the computer name of this machine and put it in the announcement
  1111. //
  1112. GetComputerNameA( MasterAnnouncementp->MasterAnnouncement.MasterName,
  1113. &ComputerNameSize);
  1114. //
  1115. // Send the announcement
  1116. //
  1117. MasterAnnouncementp->Type = MasterAnnouncement;
  1118. SendDatagramA( Transport,
  1119. EmulatedDomain,
  1120. ServerName,
  1121. ComputerName,
  1122. MasterAnnouncementp,
  1123. FIELD_OFFSET(MASTER_ANNOUNCEMENT, MasterAnnouncement.MasterName) + ComputerNameSize+sizeof(CHAR));
  1124. return;
  1125. }
  1126. VOID
  1127. IllegalDatagram(
  1128. IN PCHAR Transport,
  1129. IN PCHAR ServerName,
  1130. IN PCHAR EmulatedDomain
  1131. )
  1132. {
  1133. REQUEST_ELECTION ElectRequest;
  1134. ElectRequest.Type = Election;
  1135. SendDatagramA( Transport,
  1136. EmulatedDomain,
  1137. ServerName,
  1138. ComputerName,
  1139. &ElectRequest,
  1140. FIELD_OFFSET(REQUEST_ELECTION, ElectionRequest.TimeUp) );
  1141. return;
  1142. }
  1143. VOID
  1144. GetOtherdomains(
  1145. IN PCHAR ServerName
  1146. )
  1147. {
  1148. NET_API_STATUS Status;
  1149. ANSI_STRING AServerName;
  1150. UNICODE_STRING UServerName;
  1151. PVOID Buffer;
  1152. PSERVER_INFO_100 ServerInfo;
  1153. ULONG i;
  1154. ULONG EntriesRead;
  1155. ULONG TotalEntries;
  1156. NTSTATUS status;
  1157. RtlInitString(&AServerName, ServerName);
  1158. status = RtlAnsiStringToUnicodeString(&UServerName, &AServerName, TRUE);
  1159. if (NT_ERROR(status) || !UServerName.Buffer) {
  1160. return;
  1161. }
  1162. if ((wcslen(UServerName.Buffer) < 3) ||
  1163. wcsncmp(UServerName.Buffer, TEXT("\\\\"), 2) != 0 ||
  1164. I_NetNameValidate(NULL,
  1165. ((LPWSTR)UServerName.Buffer)+2,
  1166. NAMETYPE_COMPUTER,
  1167. 0L))
  1168. {
  1169. printf("Unable to query otherdomains: Invalid computer name\n") ;
  1170. return;
  1171. }
  1172. Status = I_BrowserQueryOtherDomains(UServerName.Buffer, (LPBYTE *)&Buffer, &EntriesRead, &TotalEntries);
  1173. if (Status != NERR_Success) {
  1174. printf("Unable to query otherdomains: %s\n", get_error_text(Status));
  1175. return;
  1176. }
  1177. printf("Other domains:\n");
  1178. ServerInfo = Buffer;
  1179. for (i = 0 ; i < EntriesRead; i++) {
  1180. printf(" %s\n", UnicodeToPrintfString(ServerInfo->sv100_name));
  1181. ServerInfo ++;
  1182. }
  1183. return;
  1184. }
  1185. VOID
  1186. View(
  1187. IN PCHAR Transport,
  1188. IN PCHAR ServerOrDomain,
  1189. IN PCHAR FlagsString,
  1190. IN PCHAR Domain,
  1191. IN BOOL GoForever
  1192. )
  1193. {
  1194. NET_API_STATUS Status;
  1195. UNICODE_STRING TransportName;
  1196. ANSI_STRING AServerName;
  1197. UNICODE_STRING UServerName;
  1198. ANSI_STRING ADomainName;
  1199. UNICODE_STRING UDomainName;
  1200. ULONG Flags ;
  1201. PVOID ServerList;
  1202. PSERVER_INFO_101 Server;
  1203. ULONG EntriesInList;
  1204. ULONG TotalEntries;
  1205. unsigned int i;
  1206. if ((ServerOrDomain && _stricmp(ServerOrDomain,"/domain")==0) ||
  1207. (Domain && _stricmp(Domain,"/domain")==0) )
  1208. {
  1209. CommandUsage( BROWSER_DEBUG_VIEW );
  1210. exit(4);
  1211. }
  1212. if (FlagsString)
  1213. {
  1214. if (_stricmp(FlagsString,"/domain")==0)
  1215. Flags = SV_TYPE_DOMAIN_ENUM ;
  1216. else
  1217. Flags = strtoul(FlagsString, NULL, 0);
  1218. }
  1219. else
  1220. Flags = SV_TYPE_ALL ;
  1221. qualify_transport(Transport, &TransportName, FALSE) ;
  1222. RtlInitString(&AServerName, ServerOrDomain);
  1223. RtlAnsiStringToUnicodeString(&UServerName, &AServerName, TRUE);
  1224. if (ARGUMENT_PRESENT(Domain)) {
  1225. RtlInitString(&ADomainName, Domain);
  1226. RtlAnsiStringToUnicodeString(&UDomainName, &ADomainName, TRUE);
  1227. //
  1228. // if domain is present, this must be computername
  1229. //
  1230. if ((wcslen(UServerName.Buffer) < 3) ||
  1231. wcsncmp(UServerName.Buffer, TEXT("\\\\"), 2) != 0 ||
  1232. I_NetNameValidate(NULL,
  1233. ((LPWSTR)UServerName.Buffer)+2,
  1234. NAMETYPE_COMPUTER,
  1235. 0L))
  1236. {
  1237. printf("Invalid computer name: %s\n", ServerOrDomain) ;
  1238. exit(1);
  1239. }
  1240. }
  1241. if (UServerName.Buffer[0] != L'\\' || UServerName.Buffer[1] != L'\\') {
  1242. PWSTR *BrowserList;
  1243. ULONG BrowserListLength;
  1244. Status = GetBrowserServerList(&TransportName, UServerName.Buffer,
  1245. &BrowserList, &BrowserListLength, FALSE);
  1246. if (Status != NERR_Success) {
  1247. printf("Unable to get backup list for %s on transport %s: %s\n", UnicodeToPrintfString(UServerName.Buffer), UnicodeToPrintfString2(TransportName.Buffer), get_error_text(Status));
  1248. exit(1);
  1249. }
  1250. if (BrowserListLength == 0) {
  1251. printf("Unable to get backup list for %s", UnicodeToPrintfString(UServerName.Buffer));
  1252. printf(" on transport %s: %s\n", UnicodeToPrintfString(TransportName.Buffer), get_error_text(Status));
  1253. exit(1);
  1254. }
  1255. UServerName.Buffer = *BrowserList;
  1256. }
  1257. printf("Remoting NetServerEnum to %s", UnicodeToPrintfString(UServerName.Buffer));
  1258. printf(" on transport %s with flags %lx\n", UnicodeToPrintfString(TransportName.Buffer), Flags);
  1259. do {
  1260. DWORD StartTime = GetTickCount();
  1261. DWORD EndTime;
  1262. Status = RxNetServerEnum(UServerName.Buffer,
  1263. TransportName.Buffer,
  1264. 101,
  1265. (LPBYTE *)&ServerList,
  1266. 0xffffffff,
  1267. &EntriesInList,
  1268. &TotalEntries,
  1269. Flags,
  1270. ARGUMENT_PRESENT(Domain) ? UDomainName.Buffer : NULL,
  1271. NULL
  1272. );
  1273. EndTime = GetTickCount();
  1274. if (Status != NERR_Success) {
  1275. printf("Unable to remote API to %s ", UnicodeToPrintfString(UServerName.Buffer));
  1276. printf("on transport %s: %s (%d milliseconds)\n", UnicodeToPrintfString(TransportName.Buffer), get_error_text(Status), EndTime - StartTime);
  1277. if (Status != ERROR_MORE_DATA) {
  1278. exit(1);
  1279. }
  1280. }
  1281. printf("%ld entries returned. %ld total. %ld milliseconds\n\n", EntriesInList, TotalEntries, EndTime-StartTime);
  1282. if (!GoForever) {
  1283. Server = ServerList;
  1284. for (i = 0; i < EntriesInList ; i ++ ) {
  1285. DisplayServerInfo101( &Server[i], Flags==SV_TYPE_DOMAIN_ENUM );
  1286. printf("\n");
  1287. }
  1288. }
  1289. NetApiBufferFree(ServerList);
  1290. } while ( GoForever );
  1291. return;
  1292. }
  1293. VOID
  1294. ListWFW(
  1295. IN PCHAR Domain
  1296. )
  1297. {
  1298. NET_API_STATUS Status;
  1299. ANSI_STRING ADomainName;
  1300. UNICODE_STRING UDomainName;
  1301. PVOID ServerList;
  1302. PSERVER_INFO_101 Server;
  1303. ULONG EntriesInList;
  1304. ULONG TotalEntries;
  1305. unsigned int i;
  1306. RtlInitString(&ADomainName, Domain);
  1307. RtlAnsiStringToUnicodeString(&UDomainName, &ADomainName, TRUE);
  1308. printf("Calling NetServerEnum to enumerate WFW servers.\n") ;
  1309. Status = NetServerEnum(NULL,
  1310. 101,
  1311. (LPBYTE *)&ServerList,
  1312. 0xffffffff,
  1313. &EntriesInList,
  1314. &TotalEntries,
  1315. SV_TYPE_WFW,
  1316. UDomainName.Buffer,
  1317. NULL) ;
  1318. if (Status != NERR_Success)
  1319. {
  1320. printf("Unable to enumerate WFW servers. Error: %s\n",
  1321. get_error_text(Status));
  1322. exit(1);
  1323. }
  1324. printf("%ld WFW servers returned. %ld total.\n",
  1325. EntriesInList,
  1326. TotalEntries);
  1327. if (EntriesInList == 0)
  1328. printf("There are WFW servers with an active Browser.\n") ;
  1329. else
  1330. {
  1331. printf("The following are running the browser:\n\n") ;
  1332. Server = ServerList;
  1333. for (i = 0; i < EntriesInList ; i ++ ) {
  1334. DWORD ServerType = Server[i].sv101_type ;
  1335. if (!(ServerType & (SV_TYPE_POTENTIAL_BROWSER |
  1336. SV_TYPE_BACKUP_BROWSER |
  1337. SV_TYPE_MASTER_BROWSER ))) {
  1338. continue ;
  1339. }
  1340. DisplayServerInfo101( &Server[i], FALSE );
  1341. printf( "\n" );
  1342. }
  1343. }
  1344. NetApiBufferFree(ServerList);
  1345. return;
  1346. }
  1347. VOID
  1348. ForceAnnounce(
  1349. IN PCHAR Transport,
  1350. IN PCHAR Domain,
  1351. IN PCHAR EmulatedDomain
  1352. )
  1353. {
  1354. REQUEST_ANNOUNCE_PACKET RequestAnnounce;
  1355. ULONG NameSize = sizeof(RequestAnnounce.RequestAnnouncement.Reply);
  1356. //
  1357. // Build the request
  1358. //
  1359. RequestAnnounce.Type = AnnouncementRequest;
  1360. RequestAnnounce.RequestAnnouncement.Flags = 0;
  1361. GetComputerNameA(RequestAnnounce.RequestAnnouncement.Reply, &NameSize);
  1362. //
  1363. // Send the request
  1364. //
  1365. SendDatagramA( Transport,
  1366. EmulatedDomain,
  1367. Domain,
  1368. BrowserElection,
  1369. &RequestAnnounce,
  1370. FIELD_OFFSET(REQUEST_ANNOUNCE_PACKET, RequestAnnouncement.Reply) + NameSize + sizeof(CHAR));
  1371. }
  1372. VOID
  1373. GetLocalList(
  1374. IN PCHAR Transport,
  1375. IN PCHAR FlagsString,
  1376. IN PCHAR EmulatedDomain
  1377. )
  1378. {
  1379. NET_API_STATUS Status;
  1380. UNICODE_STRING TransportName;
  1381. ANSI_STRING AEmulatedDomainName;
  1382. UNICODE_STRING EmulatedDomainName;
  1383. ULONG Flags = (FlagsString == NULL ? SV_TYPE_ALL : strtoul(FlagsString, NULL, 0));
  1384. PVOID ServerList;
  1385. PSERVER_INFO_101 Server;
  1386. ULONG EntriesInList;
  1387. ULONG TotalEntries;
  1388. unsigned int i;
  1389. qualify_transport(Transport, &TransportName, FALSE) ;
  1390. RtlInitString(&AEmulatedDomainName, EmulatedDomain );
  1391. RtlAnsiStringToUnicodeString(&EmulatedDomainName, &AEmulatedDomainName, TRUE);
  1392. printf("Retrieving local browser list on transport %ws\\%s with flags %lx\n", EmulatedDomainName.Buffer, UnicodeToPrintfString(TransportName.Buffer), Flags);
  1393. Status = GetLocalBrowseList (&TransportName,
  1394. &EmulatedDomainName,
  1395. 101,
  1396. Flags,
  1397. (LPBYTE *)&ServerList,
  1398. &EntriesInList,
  1399. &TotalEntries
  1400. );
  1401. if (Status != NERR_Success) {
  1402. printf("Unable to retrieve local list on transport %s: %lx\n", UnicodeToPrintfString(TransportName.Buffer), Status);
  1403. exit(1);
  1404. }
  1405. Server = ServerList;
  1406. printf("%ld entries returned. %ld total.\n", EntriesInList, TotalEntries);
  1407. for (i = 0; i < EntriesInList ; i ++ ) {
  1408. DisplayServerInfo101( &Server[i], Flags==SV_TYPE_DOMAIN_ENUM );
  1409. if (Flags == SV_TYPE_BACKUP_BROWSER) {
  1410. PUSHORT BrowserVersion = (PUSHORT)Server[i].sv101_comment - 1;
  1411. printf(" V:%4.4x", *BrowserVersion);
  1412. }
  1413. printf("\n") ;
  1414. }
  1415. return;
  1416. }
  1417. NET_API_STATUS
  1418. GetLocalBrowseList(
  1419. IN PUNICODE_STRING Network,
  1420. IN PUNICODE_STRING EmulatedDomainName,
  1421. IN ULONG Level,
  1422. IN ULONG ServerType,
  1423. OUT PVOID *ServerList,
  1424. OUT PULONG EntriesRead,
  1425. OUT PULONG TotalEntries
  1426. )
  1427. {
  1428. NET_API_STATUS status;
  1429. PLMDR_REQUEST_PACKET Drp; // Datagram receiver request packet
  1430. ULONG DrpSize;
  1431. HANDLE BrowserHandle;
  1432. LPBYTE Where;
  1433. OpenBrowser(&BrowserHandle);
  1434. //
  1435. // Allocate the request packet large enough to hold the variable length
  1436. // domain name.
  1437. //
  1438. DrpSize = sizeof(LMDR_REQUEST_PACKET) +
  1439. Network->Length + sizeof(WCHAR) +
  1440. EmulatedDomainName->Length + sizeof(WCHAR);
  1441. if ((Drp = malloc(DrpSize)) == NULL) {
  1442. return GetLastError();
  1443. }
  1444. //
  1445. // Set up request packet. Output buffer structure is of enumerate
  1446. // servers type.
  1447. //
  1448. Drp->Version = LMDR_REQUEST_PACKET_VERSION_DOM;
  1449. Drp->Type = EnumerateServers;
  1450. Drp->Level = Level;
  1451. Drp->Parameters.EnumerateServers.ServerType = ServerType;
  1452. Drp->Parameters.EnumerateServers.ResumeHandle = 0;
  1453. Drp->Parameters.EnumerateServers.DomainNameLength = 0;
  1454. Drp->Parameters.EnumerateServers.DomainName[0] = '\0';
  1455. Where = ((PCHAR)Drp+sizeof(LMDR_REQUEST_PACKET));
  1456. wcscpy( (LPWSTR)Where, Network->Buffer );
  1457. RtlInitUnicodeString( &Drp->TransportName, (LPWSTR) Where );
  1458. Where += Drp->TransportName.MaximumLength;
  1459. wcscpy( (LPWSTR)Where, EmulatedDomainName->Buffer );
  1460. RtlInitUnicodeString( &Drp->EmulatedDomainName, (LPWSTR) Where );
  1461. #ifdef notdef
  1462. Where += Drp->EmulatedDomainName.MaximumLength;
  1463. #endif // notdef
  1464. //
  1465. // Ask the datagram receiver to enumerate the servers
  1466. //
  1467. status = DeviceControlGetInfo(
  1468. BrowserHandle,
  1469. IOCTL_LMDR_ENUMERATE_SERVERS,
  1470. Drp,
  1471. DrpSize,
  1472. ServerList,
  1473. 0xffffffff,
  1474. 4096,
  1475. NULL
  1476. );
  1477. *EntriesRead = Drp->Parameters.EnumerateServers.EntriesRead;
  1478. *TotalEntries = Drp->Parameters.EnumerateServers.TotalEntries;
  1479. (void) free(Drp);
  1480. return status;
  1481. }
  1482. VOID
  1483. PrintNetbiosNames(
  1484. IN PCHAR Transport,
  1485. IN PCHAR EmulatedDomain OPTIONAL
  1486. )
  1487. /*++
  1488. Routine Description:
  1489. Prints the list of Netbios names registered on a particular transport
  1490. Arguments:
  1491. Transport - Transport to query
  1492. EmulatedDomain - Emulated domain to query
  1493. #endif
  1494. Return Value:
  1495. None
  1496. --*/
  1497. {
  1498. NET_API_STATUS Status;
  1499. UNICODE_STRING TransportName;
  1500. ANSI_STRING AEmulatedDomainName;
  1501. UNICODE_STRING EmulatedDomainName;
  1502. PVOID NameList;
  1503. PDGRECEIVE_NAMES Names;
  1504. ULONG EntriesInList;
  1505. ULONG TotalEntries;
  1506. unsigned int i;
  1507. //
  1508. // Get the netbios names
  1509. //
  1510. qualify_transport(Transport, &TransportName, FALSE ) ;
  1511. RtlInitString(&AEmulatedDomainName, EmulatedDomain );
  1512. RtlAnsiStringToUnicodeString(&EmulatedDomainName, &AEmulatedDomainName, TRUE);
  1513. printf("Retrieving browser Netbios names on transport %ws\\%ws\n", EmulatedDomainName.Buffer, TransportName.Buffer);
  1514. Status = GetNetbiosNames(&TransportName,
  1515. &EmulatedDomainName,
  1516. &NameList,
  1517. &EntriesInList,
  1518. &TotalEntries
  1519. );
  1520. if (Status != NERR_Success) {
  1521. printf("Unable to retrieve Netbios names on transport %ws: %lx\n", TransportName.Buffer, Status);
  1522. exit(1);
  1523. }
  1524. //
  1525. // Print the netbios names.
  1526. //
  1527. Names = NameList;
  1528. printf("%ld entries returned. %ld total.\n", EntriesInList, TotalEntries);
  1529. for (i = 0; i < EntriesInList ; i ++ ) {
  1530. if ( Names[i].Type == DomainAnnouncement ) {
  1531. printf("%-16.16s", "__MSBROWSE__" );
  1532. } else {
  1533. printf("%-16.16wZ", &Names[i].DGReceiverName );
  1534. }
  1535. switch ( Names[i].Type ) {
  1536. case ComputerName:
  1537. printf("<00> ComputerName"); break;
  1538. case AlternateComputerName:
  1539. printf("<00> AlternateComputerName"); break;
  1540. case PrimaryDomain:
  1541. printf("<00> PrimaryDomain"); break;
  1542. case LogonDomain:
  1543. printf("<00> LogonDomain"); break;
  1544. case OtherDomain:
  1545. printf("<00> OtherDomain"); break;
  1546. case DomainAnnouncement:
  1547. printf("DomainAnnouncement"); break;
  1548. case MasterBrowser:
  1549. printf("<1D> MasterBrowser"); break;
  1550. case BrowserElection:
  1551. printf("<1E> BrowserElection"); break;
  1552. case BrowserServer:
  1553. printf("<20> BrowserServer"); break;
  1554. case DomainName:
  1555. printf("<1C> DomainName"); break;
  1556. case PrimaryDomainBrowser:
  1557. printf("<1B> DomainMasterBrowser"); break;
  1558. default:
  1559. printf("<Unknown>"); break;
  1560. }
  1561. printf("\n") ;
  1562. }
  1563. return;
  1564. }
  1565. NET_API_STATUS
  1566. GetNetbiosNames(
  1567. IN PUNICODE_STRING Network,
  1568. IN PUNICODE_STRING EmulatedDomainName,
  1569. OUT PVOID *NameList,
  1570. OUT PULONG EntriesRead,
  1571. OUT PULONG TotalEntries
  1572. )
  1573. {
  1574. NET_API_STATUS status;
  1575. PLMDR_REQUEST_PACKET Drp; // Datagram receiver request packet
  1576. ULONG DrpSize;
  1577. HANDLE BrowserHandle;
  1578. LPBYTE Where;
  1579. OpenBrowser(&BrowserHandle);
  1580. //
  1581. // Allocate the request packet large enough to hold the variable length
  1582. // domain name.
  1583. //
  1584. DrpSize = sizeof(LMDR_REQUEST_PACKET) +
  1585. Network->Length + sizeof(WCHAR) +
  1586. EmulatedDomainName->Length + sizeof(WCHAR);
  1587. if ((Drp = malloc(DrpSize)) == NULL) {
  1588. return GetLastError();
  1589. }
  1590. //
  1591. // Set up request packet. Output buffer structure is of enumerate
  1592. // servers type.
  1593. //
  1594. Drp->Version = LMDR_REQUEST_PACKET_VERSION_DOM;
  1595. Drp->Type = EnumerateNames;
  1596. Drp->Level = 0;
  1597. Drp->Parameters.EnumerateNames.ResumeHandle = 0;
  1598. Where = ((PCHAR)Drp+sizeof(LMDR_REQUEST_PACKET));
  1599. wcscpy( (LPWSTR)Where, Network->Buffer );
  1600. RtlInitUnicodeString( &Drp->TransportName, (LPWSTR) Where );
  1601. Where += Drp->TransportName.MaximumLength;
  1602. wcscpy( (LPWSTR)Where, EmulatedDomainName->Buffer );
  1603. RtlInitUnicodeString( &Drp->EmulatedDomainName, (LPWSTR) Where );
  1604. #ifdef notdef
  1605. Where += Drp->EmulatedDomainName.MaximumLength;
  1606. #endif // notdef
  1607. //
  1608. // Ask the datagram receiver to enumerate the names
  1609. //
  1610. status = DeviceControlGetInfo(
  1611. BrowserHandle,
  1612. IOCTL_LMDR_ENUMERATE_NAMES,
  1613. Drp,
  1614. DrpSize,
  1615. NameList,
  1616. 0xffffffff,
  1617. 4096,
  1618. NULL );
  1619. *EntriesRead = Drp->Parameters.EnumerateNames.EntriesRead;
  1620. *TotalEntries = Drp->Parameters.EnumerateNames.TotalEntries;
  1621. (void) free(Drp);
  1622. return status;
  1623. }
  1624. NET_API_STATUS
  1625. AddAlternateComputerName(
  1626. IN PCHAR Transport,
  1627. IN PCHAR ComputerName,
  1628. IN PCHAR EmulatedDomain
  1629. )
  1630. /*++
  1631. Routine Description:
  1632. This function adds an alternate compture name on the specified transport.
  1633. Arguments:
  1634. Transport - Transport to add the computer name on.
  1635. ComputerName - Alternate computer name to add
  1636. EmulatedDomain - Emulated Domain to add computer name on
  1637. Return Value:
  1638. Status - The status of the operation.
  1639. --*/
  1640. {
  1641. NET_API_STATUS Status;
  1642. HANDLE BrowserHandle;
  1643. LPBYTE Where;
  1644. PLMDR_REQUEST_PACKET RequestPacket = NULL;
  1645. UNICODE_STRING TransportName;
  1646. WCHAR UnicodeComputerName[CNLEN+1];
  1647. UNICODE_STRING EmulatedDomainName;
  1648. ANSI_STRING AEmulatedDomainName;
  1649. //
  1650. // Qualify the transport name and convert it to unicode
  1651. //
  1652. qualify_transport(Transport, &TransportName, FALSE) ;
  1653. NetpCopyStrToWStr( UnicodeComputerName, ComputerName );
  1654. //
  1655. // Convert the emulated domain name to unicode
  1656. //
  1657. RtlInitString(&AEmulatedDomainName, EmulatedDomain);
  1658. RtlAnsiStringToUnicodeString(&EmulatedDomainName, &AEmulatedDomainName, TRUE);
  1659. RequestPacket = malloc(sizeof(LMDR_REQUEST_PACKET)+(LM20_CNLEN+1)*sizeof(WCHAR));
  1660. if (RequestPacket == NULL) {
  1661. return(ERROR_NOT_ENOUGH_MEMORY);
  1662. }
  1663. Status = OpenBrowser(&BrowserHandle);
  1664. if (Status != NERR_Success) {
  1665. free(RequestPacket);
  1666. return(Status);
  1667. }
  1668. RequestPacket->Version = LMDR_REQUEST_PACKET_VERSION;
  1669. RequestPacket->TransportName = TransportName;
  1670. RequestPacket->EmulatedDomainName = EmulatedDomainName;
  1671. RequestPacket->Parameters.AddDelName.Type = AlternateComputerName;
  1672. RequestPacket->Parameters.AddDelName.DgReceiverNameLength =
  1673. wcslen(UnicodeComputerName)*sizeof(WCHAR);
  1674. wcscpy(RequestPacket->Parameters.AddDelName.Name, UnicodeComputerName);
  1675. Where = ((LPBYTE)(RequestPacket->Parameters.AddDelName.Name)) +
  1676. RequestPacket->Parameters.AddDelName.DgReceiverNameLength +
  1677. sizeof(WCHAR);
  1678. //
  1679. // Reference the network while the I/O is pending.
  1680. //
  1681. Status = BrDgReceiverIoControl(BrowserHandle,
  1682. IOCTL_LMDR_ADD_NAME_DOM,
  1683. RequestPacket,
  1684. (DWORD)(Where - (LPBYTE)RequestPacket),
  1685. NULL,
  1686. 0,
  1687. NULL);
  1688. if (Status != NERR_Success) {
  1689. printf("Browser: Unable to add name for network %s: %ld\n", UnicodeToPrintfString(TransportName.Buffer), Status);
  1690. free(RequestPacket);
  1691. return(Status);
  1692. }
  1693. free(RequestPacket);
  1694. return Status;
  1695. }
  1696. NET_API_STATUS
  1697. BrBindToTransport(
  1698. IN BOOL IsBind,
  1699. IN HANDLE BrowserHandle,
  1700. IN LPWSTR TransportName,
  1701. IN LPWSTR EmulatedDomainName,
  1702. IN LPWSTR EmulatedComputerName
  1703. )
  1704. {
  1705. NET_API_STATUS Status;
  1706. UCHAR PacketBuffer[sizeof(LMDR_REQUEST_PACKET)+(MAXIMUM_FILENAME_LENGTH+1+CNLEN+1)*sizeof(WCHAR)];
  1707. PLMDR_REQUEST_PACKET RequestPacket = (PLMDR_REQUEST_PACKET)PacketBuffer;
  1708. RequestPacket->Version = LMDR_REQUEST_PACKET_VERSION_DOM;
  1709. RequestPacket->TransportName.Length = 0;
  1710. RequestPacket->TransportName.MaximumLength = 0;
  1711. RtlInitUnicodeString( &RequestPacket->EmulatedDomainName, EmulatedDomainName );
  1712. RequestPacket->Parameters.Bind.TransportNameLength = STRLEN(TransportName)*sizeof(TCHAR);
  1713. STRCPY(RequestPacket->Parameters.Bind.TransportName, TransportName);
  1714. if ( IsBind ) {
  1715. RequestPacket->Level = TRUE; // EmulatedComputerName follows transport name
  1716. STRCAT(RequestPacket->Parameters.Bind.TransportName, EmulatedComputerName );
  1717. }
  1718. //
  1719. // This is a simple IoControl - It just updates the status.
  1720. //
  1721. Status = BrDgReceiverIoControl(
  1722. BrowserHandle,
  1723. IsBind ? IOCTL_LMDR_BIND_TO_TRANSPORT_DOM : IOCTL_LMDR_UNBIND_FROM_TRANSPORT_DOM,
  1724. RequestPacket,
  1725. FIELD_OFFSET(LMDR_REQUEST_PACKET, Parameters.Bind.TransportName) +
  1726. RequestPacket->Parameters.Bind.TransportNameLength +
  1727. wcslen(EmulatedComputerName) * sizeof(WCHAR) + sizeof(WCHAR),
  1728. NULL,
  1729. 0,
  1730. NULL);
  1731. return Status;
  1732. }
  1733. NET_API_STATUS
  1734. BindTransport(
  1735. IN BOOL IsBind,
  1736. IN PCHAR Transport,
  1737. IN PCHAR EmulatedDomain,
  1738. IN PCHAR ComputerName
  1739. )
  1740. /*++
  1741. Routine Description:
  1742. This function binds the bowser to a particular transport.
  1743. Arguments:
  1744. IsBind - True for a bind. False for an unbind.
  1745. Transport - Transport to bind to.
  1746. EmulatedDomain - Emulated Domain to add computer name on
  1747. ComputerName - Alternate computer name to add
  1748. Return Value:
  1749. Status - The status of the operation.
  1750. --*/
  1751. {
  1752. NET_API_STATUS Status;
  1753. HANDLE BrowserHandle;
  1754. LPBYTE Where;
  1755. PLMDR_REQUEST_PACKET RequestPacket = NULL;
  1756. UNICODE_STRING TransportName;
  1757. WCHAR UnicodeComputerName[CNLEN+1];
  1758. WCHAR UnicodeDomainName[DNLEN+1];
  1759. //
  1760. // Qualify the transport name and convert it to unicode
  1761. //
  1762. qualify_transport(Transport, &TransportName, IsBind) ;
  1763. if ( ComputerName == NULL ) {
  1764. *UnicodeComputerName = L'\0';
  1765. } else {
  1766. NetpCopyStrToWStr( UnicodeComputerName, ComputerName );
  1767. }
  1768. if ( EmulatedDomain == NULL ) {
  1769. *UnicodeDomainName = L'\0';
  1770. } else {
  1771. NetpCopyStrToWStr( UnicodeDomainName, EmulatedDomain );
  1772. }
  1773. //
  1774. // Open the browser driver.
  1775. Status = OpenBrowser(&BrowserHandle);
  1776. if (Status != NERR_Success) {
  1777. return(Status);
  1778. }
  1779. //
  1780. //
  1781. Status = BrBindToTransport(
  1782. IsBind,
  1783. BrowserHandle,
  1784. TransportName.Buffer,
  1785. UnicodeDomainName,
  1786. UnicodeComputerName );
  1787. if (Status != NERR_Success) {
  1788. printf("Browser: Unable to bind to network %s: %ld\n", UnicodeToPrintfString(TransportName.Buffer), Status);
  1789. }
  1790. return Status;
  1791. }
  1792. VOID
  1793. Announce(
  1794. IN PCHAR Transport,
  1795. IN PCHAR Domain,
  1796. IN PCHAR EmulatedDomain,
  1797. IN BOOL AsMaster
  1798. )
  1799. {
  1800. NET_API_STATUS NetStatus;
  1801. PSERVER_INFO_101 ServerInfo;
  1802. PWKSTA_INFO_101 WkstaInfo;
  1803. UNICODE_STRING TransportName;
  1804. LPBYTE Buffer;
  1805. ULONG BrowserType;
  1806. ULONG OriginalBrowserType;
  1807. WCHAR UDomain[256];
  1808. WCHAR ServerComment[256];
  1809. WCHAR ServerName[256];
  1810. BOOLEAN IsLocalDomain;
  1811. SERVICE_STATUS ServiceStatus;
  1812. DWORD VersionMajor;
  1813. DWORD VersionMinor;
  1814. BOOL UsedDefaultChar;
  1815. #define ANN_BITS_OF_INTEREST (SV_TYPE_BACKUP_BROWSER | SV_TYPE_POTENTIAL_BROWSER | SV_TYPE_MASTER_BROWSER)
  1816. qualify_transport(Transport, &TransportName, FALSE ) ;
  1817. MultiByteToWideChar(CP_ACP, 0, Domain, strlen(Domain)+1, UDomain, 255);
  1818. NetServerGetInfo(NULL, 101, &Buffer);
  1819. ServerInfo = (PSERVER_INFO_101 )Buffer;
  1820. BrowserType = ServerInfo->sv101_type & ANN_BITS_OF_INTEREST;
  1821. wcscpy(ServerComment, ServerInfo->sv101_comment);
  1822. wcscpy(ServerName, ServerInfo->sv101_name);
  1823. VersionMajor = ServerInfo->sv101_version_major;
  1824. VersionMinor = ServerInfo->sv101_version_minor;
  1825. NetApiBufferFree(Buffer);
  1826. NetWkstaGetInfo(NULL, 101, &Buffer);
  1827. WkstaInfo = (PWKSTA_INFO_101 )Buffer;
  1828. IsLocalDomain = !_wcsicmp(UDomain, WkstaInfo->wki101_langroup);
  1829. NetApiBufferFree(Buffer);
  1830. OriginalBrowserType = BrowserType;
  1831. if (AsMaster) {
  1832. BrowserType |= SV_TYPE_MASTER_BROWSER;
  1833. }
  1834. //
  1835. // If the browser is running, and this is our local domain, have the
  1836. // server do the announcing.
  1837. //
  1838. if (IsLocalDomain &&
  1839. CheckForService(SERVICE_BROWSER, &ServiceStatus) == NERR_Success ) {
  1840. printf("Toggling local server status bits to %lx and then to %lx\n",
  1841. BrowserType, OriginalBrowserType);
  1842. I_NetServerSetServiceBitsEx(NULL, NULL, TransportName.Buffer, ANN_BITS_OF_INTEREST, BrowserType, TRUE);
  1843. I_NetServerSetServiceBitsEx(NULL, NULL, TransportName.Buffer, ANN_BITS_OF_INTEREST, OriginalBrowserType, TRUE);
  1844. } else {
  1845. BROWSE_ANNOUNCE_PACKET BrowseAnnouncement;
  1846. printf("Announcing to domain %s by hand\n", UnicodeToPrintfString(UDomain));
  1847. BrowseAnnouncement.BrowseType = (AsMaster ? LocalMasterAnnouncement : HostAnnouncement);
  1848. BrowseAnnouncement.BrowseAnnouncement.UpdateCount = 0;
  1849. WideCharToMultiByte(CP_OEMCP, 0,
  1850. ServerName,
  1851. wcslen(ServerName)+1,
  1852. BrowseAnnouncement.BrowseAnnouncement.ServerName,
  1853. LM20_CNLEN+1,
  1854. "?",
  1855. &UsedDefaultChar
  1856. );
  1857. BrowseAnnouncement.BrowseAnnouncement.VersionMajor = (UCHAR)VersionMajor;
  1858. BrowseAnnouncement.BrowseAnnouncement.VersionMinor = (UCHAR)VersionMinor;
  1859. BrowseAnnouncement.BrowseAnnouncement.Type = BrowserType;
  1860. WideCharToMultiByte(CP_OEMCP, 0,
  1861. ServerComment,
  1862. wcslen(ServerComment),
  1863. BrowseAnnouncement.BrowseAnnouncement.Comment,
  1864. LM20_MAXCOMMENTSZ+1,
  1865. "?",
  1866. &UsedDefaultChar
  1867. );
  1868. BrowseAnnouncement.BrowseAnnouncement.CommentPointer = 0;
  1869. //
  1870. // Send the request
  1871. //
  1872. NetStatus = SendDatagramA(
  1873. Transport,
  1874. EmulatedDomain,
  1875. Domain,
  1876. (AsMaster ? BrowserElection : MasterBrowser),
  1877. &BrowseAnnouncement,
  1878. sizeof(BrowseAnnouncement));
  1879. if ( NetStatus != NO_ERROR ) {
  1880. printf( "Couldn't send datagram: %s\n", get_error_text(NetStatus) );
  1881. }
  1882. }
  1883. return;
  1884. }
  1885. VOID
  1886. RpcList(
  1887. IN PCHAR Transport,
  1888. IN PCHAR ServerOrDomain,
  1889. IN PCHAR FlagsString,
  1890. IN BOOL GoForever
  1891. )
  1892. {
  1893. NET_API_STATUS Status;
  1894. UNICODE_STRING TransportName;
  1895. ANSI_STRING AServerName;
  1896. UNICODE_STRING UServerName;
  1897. ULONG Flags = (FlagsString == NULL ? SV_TYPE_ALL : strtoul(FlagsString, NULL, 0));
  1898. PVOID ServerList;
  1899. PSERVER_INFO_101 Server;
  1900. ULONG EntriesInList;
  1901. ULONG TotalEntries;
  1902. unsigned int i;
  1903. qualify_transport(Transport, &TransportName, FALSE) ;
  1904. RtlInitString(&AServerName, ServerOrDomain);
  1905. Status = RtlAnsiStringToUnicodeString(&UServerName, &AServerName, TRUE);
  1906. if (ERROR_SUCCESS != Status) {
  1907. printf("Error: Failed to create string (out of memory?)\n");
  1908. exit(1);
  1909. }
  1910. if (UServerName.Buffer[0] != L'\\' || UServerName.Buffer[1] != L'\\') {
  1911. PWSTR *BrowserList;
  1912. ULONG BrowserListLength;
  1913. Status = GetBrowserServerList(&TransportName, UServerName.Buffer,
  1914. &BrowserList, &BrowserListLength, FALSE);
  1915. if (Status != NERR_Success) {
  1916. printf("Unable to get backup list for %s", UnicodeToPrintfString(UServerName.Buffer));
  1917. printf(" on transport %s: %s\n", UnicodeToPrintfString(TransportName.Buffer), get_error_text(Status));
  1918. exit(1);
  1919. }
  1920. if (BrowserListLength == 0) {
  1921. printf("Unable to get backup list for %s", UnicodeToPrintfString(UServerName.Buffer));
  1922. printf(" on transport %s: %s\n",
  1923. UnicodeToPrintfString(TransportName.Buffer), get_error_text(Status));
  1924. exit(1);
  1925. }
  1926. UServerName.Buffer = *BrowserList;
  1927. }
  1928. printf("Remoting I_BrowserServerEnum to %s", UnicodeToPrintfString(UServerName.Buffer));
  1929. printf(" on transport %s with flags %lx\n", UnicodeToPrintfString(TransportName.Buffer), Flags);
  1930. do {
  1931. Status = I_BrowserServerEnum(UServerName.Buffer,
  1932. TransportName.Buffer,
  1933. NULL,
  1934. 101,
  1935. (LPBYTE *)&ServerList,
  1936. 0xffffffff,
  1937. &EntriesInList,
  1938. &TotalEntries,
  1939. Flags,
  1940. NULL,
  1941. NULL
  1942. );
  1943. if (Status != NERR_Success) {
  1944. printf("Unable to remote API to %s", UnicodeToPrintfString(UServerName.Buffer));
  1945. printf(" on transport %s: %s\n",UnicodeToPrintfString(TransportName.Buffer), get_error_text(Status));
  1946. if (Status != ERROR_MORE_DATA) {
  1947. exit(1);
  1948. }
  1949. }
  1950. printf("%ld entries returned. %ld total.\n", EntriesInList, TotalEntries);
  1951. if (!GoForever) {
  1952. Server = ServerList;
  1953. for (i = 0; i < EntriesInList ; i ++ ) {
  1954. DisplayServerInfo101( &Server[i], Flags==SV_TYPE_DOMAIN_ENUM );
  1955. printf( "\n" );
  1956. }
  1957. }
  1958. NetApiBufferFree(ServerList);
  1959. } while ( GoForever );
  1960. return;
  1961. }
  1962. VOID
  1963. RpcCmp(
  1964. IN PCHAR Transport,
  1965. IN PCHAR ServerOrDomain,
  1966. IN PCHAR FlagsString,
  1967. IN BOOL GoForever
  1968. )
  1969. {
  1970. NET_API_STATUS Status;
  1971. UNICODE_STRING TransportName;
  1972. ANSI_STRING AServerName;
  1973. UNICODE_STRING UServerName;
  1974. ULONG Flags = (FlagsString == NULL ? SV_TYPE_ALL : strtoul(FlagsString, NULL, 0));
  1975. PVOID RpcServerList;
  1976. PVOID RxServerList;
  1977. PSERVER_INFO_101 RpcServer;
  1978. PSERVER_INFO_101 RxServer;
  1979. ULONG RpcEntriesInList;
  1980. ULONG RpcTotalEntries;
  1981. ULONG RxEntriesInList;
  1982. ULONG RxTotalEntries;
  1983. unsigned int i;
  1984. unsigned int j;
  1985. qualify_transport(Transport, &TransportName, FALSE) ;
  1986. RtlInitString(&AServerName, ServerOrDomain);
  1987. Status = RtlAnsiStringToUnicodeString(&UServerName, &AServerName, TRUE);
  1988. if (ERROR_SUCCESS != Status) {
  1989. printf("Error: Unable to create string (out of memory?)\n");
  1990. exit(1);
  1991. }
  1992. if (UServerName.Buffer[0] != L'\\' || UServerName.Buffer[1] != L'\\') {
  1993. PWSTR *BrowserList;
  1994. ULONG BrowserListLength;
  1995. Status = GetBrowserServerList(&TransportName, UServerName.Buffer,
  1996. &BrowserList, &BrowserListLength, FALSE);
  1997. if (Status != NERR_Success) {
  1998. printf("Unable to get backup list for %s on transport %s: %lx\n", UnicodeToPrintfString(UServerName.Buffer), UnicodeToPrintfString2(TransportName.Buffer), Status);
  1999. exit(1);
  2000. }
  2001. if (BrowserListLength == 0) {
  2002. printf("Unable to get backup list for %s on transport %s: %lx\n", UnicodeToPrintfString(UServerName.Buffer), UnicodeToPrintfString2(TransportName.Buffer), Status);
  2003. exit(1);
  2004. }
  2005. UServerName.Buffer = *BrowserList;
  2006. }
  2007. printf("Remoting I_BrowserServerEnum to %s on transport %s with flags %lx\n", UnicodeToPrintfString(UServerName.Buffer), UnicodeToPrintfString2(TransportName.Buffer), Flags);
  2008. do {
  2009. Status = I_BrowserServerEnum(UServerName.Buffer,
  2010. TransportName.Buffer,
  2011. NULL,
  2012. 101,
  2013. (LPBYTE *)&RpcServerList,
  2014. 0xffffffff,
  2015. &RpcEntriesInList,
  2016. &RpcTotalEntries,
  2017. Flags,
  2018. NULL,
  2019. NULL
  2020. );
  2021. if (Status != NERR_Success) {
  2022. printf("Unable to remote API to %s on transport %s: %ld\n", UnicodeToPrintfString(UServerName.Buffer), UnicodeToPrintfString2(TransportName.Buffer), Status);
  2023. exit(1);
  2024. }
  2025. printf("%ld entries returned from RPC. %ld total.\n", RpcEntriesInList, RpcTotalEntries);
  2026. if (RpcEntriesInList != RpcTotalEntries) {
  2027. printf("EntriesRead != TotalEntries from remoted server enum\n");
  2028. }
  2029. if (RpcEntriesInList <= 20) {
  2030. printf("EntriesInList returned %ld from remoted server enum\n", RpcEntriesInList);
  2031. }
  2032. Status = RxNetServerEnum(UServerName.Buffer,
  2033. TransportName.Buffer,
  2034. 101,
  2035. (LPBYTE *)&RxServerList,
  2036. 0xffffffff,
  2037. &RxEntriesInList,
  2038. &RxTotalEntries,
  2039. Flags,
  2040. NULL,
  2041. NULL
  2042. );
  2043. if (Status != NERR_Success) {
  2044. printf("Unable to remote API to %s on transport %s: %ld\n", UnicodeToPrintfString(UServerName.Buffer), UnicodeToPrintfString2(TransportName.Buffer), Status);
  2045. exit(1);
  2046. }
  2047. printf("%ld entries returned from RX. %ld total.\n", RxEntriesInList, RxTotalEntries);
  2048. if (RxEntriesInList != RxTotalEntries) {
  2049. printf("RxEntriesRead != RxEntriesInList from remoted server enum\n");
  2050. }
  2051. if (RxEntriesInList <= 20) {
  2052. printf("RxEntriesInList returned %ld from remoted server enum\n", RxEntriesInList);
  2053. }
  2054. if (RxEntriesInList != RpcEntriesInList) {
  2055. printf("RxEntriesRead (%ld) != RpcTotalEntries (%ld) from remoted server enum\n", RxEntriesInList, RpcEntriesInList);
  2056. }
  2057. RxServer = RxServerList;
  2058. RpcServer = RpcServerList;
  2059. for (i = 0; i < RxEntriesInList ; i ++ ) {
  2060. for (j = 0; j < RpcEntriesInList ; j++) {
  2061. if (RxServer[i].sv101_name != NULL &&
  2062. RpcServer[j].sv101_name != NULL) {
  2063. if (!wcscmp(RxServer[i].sv101_name, RpcServer[j].sv101_name)) {
  2064. RxServer[i].sv101_name = NULL;
  2065. RpcServer[j].sv101_name = NULL;
  2066. break;
  2067. }
  2068. }
  2069. }
  2070. }
  2071. for (i = 0; i < RpcEntriesInList ; i++ ) {
  2072. if (RpcServer[i].sv101_name != NULL) {
  2073. printf("Rpc Server not in Rx List: %s\n", UnicodeToPrintfString(RpcServer[i].sv101_name));
  2074. }
  2075. }
  2076. for (i = 0; i < RxEntriesInList ; i++ ) {
  2077. if (RxServer[i].sv101_name != NULL) {
  2078. printf("Rx Server not in Rpc List: %s\n", UnicodeToPrintfString(RxServer[i].sv101_name));
  2079. }
  2080. }
  2081. NetApiBufferFree(RxServerList);
  2082. NetApiBufferFree(RpcServerList);
  2083. } while ( GoForever );
  2084. return;
  2085. }
  2086. CHAR * format_dlword(ULONG high, ULONG low, CHAR * buf);
  2087. VOID
  2088. revstr_add(CHAR * target, CHAR * source);
  2089. VOID
  2090. DumpStatistics(
  2091. IN ULONG NArgs,
  2092. IN PCHAR Arg1
  2093. )
  2094. {
  2095. PBROWSER_STATISTICS Statistics = NULL;
  2096. NET_API_STATUS Status;
  2097. CHAR Buffer[256];
  2098. WCHAR ServerName[256];
  2099. LPTSTR Server = NULL;
  2100. BOOL ResetStatistics = FALSE;
  2101. if (NArgs == 2) {
  2102. Server = NULL;
  2103. ResetStatistics = FALSE;
  2104. } else if (NArgs == 3) {
  2105. if (*Arg1 == '\\') {
  2106. MultiByteToWideChar(CP_ACP, 0, Arg1, strlen(Arg1)+1, ServerName, 255);
  2107. Server = ServerName;
  2108. ResetStatistics = FALSE;
  2109. } else {
  2110. Server = NULL;
  2111. ResetStatistics = TRUE;
  2112. }
  2113. } else if (*Arg1 == '\\') {
  2114. MultiByteToWideChar(CP_ACP, 0, Arg1, strlen(Arg1)+1, ServerName, 255);
  2115. Server = ServerName;
  2116. ResetStatistics = TRUE;
  2117. }
  2118. if (ResetStatistics) {
  2119. Status = I_BrowserResetStatistics(Server);
  2120. if (Status != NERR_Success) {
  2121. printf("Unable to reset browser statistics: %ld\n", Status);
  2122. exit(1);
  2123. }
  2124. } else {
  2125. FILETIME LocalFileTime;
  2126. SYSTEMTIME LocalSystemTime;
  2127. Status = I_BrowserQueryStatistics(Server, &Statistics);
  2128. if (Status != NERR_Success) {
  2129. printf("Unable to query browser statistics: %ld\n", Status);
  2130. exit(1);
  2131. }
  2132. if (!FileTimeToLocalFileTime((LPFILETIME)&Statistics->StatisticsStartTime, &LocalFileTime)) {
  2133. printf("Unable to convert statistics start time: %ld\n", GetLastError());
  2134. exit(1);
  2135. }
  2136. if (!FileTimeToSystemTime(&LocalFileTime, &LocalSystemTime)) {
  2137. printf("Unable to convert statistics start time to system time: %ld\n", GetLastError());
  2138. exit(1);
  2139. }
  2140. printf("Browser statistics since %ld:%ld:%ld.%ld on %ld/%d/%d\n",
  2141. LocalSystemTime.wHour,
  2142. LocalSystemTime.wMinute,
  2143. LocalSystemTime.wSecond,
  2144. LocalSystemTime.wMilliseconds,
  2145. LocalSystemTime.wMonth,
  2146. LocalSystemTime.wDay,
  2147. LocalSystemTime.wYear);
  2148. printf("NumberOfServerEnumerations:\t\t\t%d\n", Statistics->NumberOfServerEnumerations);
  2149. printf("NumberOfDomainEnumerations:\t\t\t%d\n", Statistics->NumberOfDomainEnumerations);
  2150. printf("NumberOfOtherEnumerations:\t\t\t%d\n", Statistics->NumberOfOtherEnumerations);
  2151. printf("NumberOfMailslotWrites:\t\t\t\t%d\n", Statistics->NumberOfMailslotWrites);
  2152. printf("NumberOfServerAnnouncements:\t\t\t%s\n", format_dlword(Statistics->NumberOfServerAnnouncements.HighPart, Statistics->NumberOfServerAnnouncements.LowPart, Buffer));
  2153. printf("NumberOfDomainAnnouncements:\t\t\t%s\n", format_dlword(Statistics->NumberOfDomainAnnouncements.HighPart, Statistics->NumberOfDomainAnnouncements.LowPart, Buffer));
  2154. printf("NumberOfElectionPackets:\t\t\t%d\n", Statistics->NumberOfElectionPackets);
  2155. printf("NumberOfGetBrowserServerListRequests:\t\t%d\n", Statistics->NumberOfGetBrowserServerListRequests);
  2156. printf("NumberOfMissedGetBrowserServerListRequests:\t%d\n", Statistics->NumberOfMissedGetBrowserServerListRequests);
  2157. printf("NumberOfDroppedServerAnnouncements:\t\t%d\n", Statistics->NumberOfMissedServerAnnouncements);
  2158. printf("NumberOfDroppedMailslotDatagrams:\t\t%d\n", Statistics->NumberOfMissedMailslotDatagrams);
  2159. // printf("NumberOfFailedMailslotAllocations:\t\t%d\n", Statistics->NumberOfFailedMailslotAllocations);
  2160. printf("NumberOfFailedMailslotReceives:\t\t\t%d\n", Statistics->NumberOfFailedMailslotReceives);
  2161. // printf("NumberOfFailedMailslotWrites:\t\t\t%d\n", Statistics->NumberOfFailedMailslotWrites);
  2162. // printf("NumberOfFailedMailslotOpens:\t\t\t%d\n", Statistics->NumberOfFailedMailslotOpens);
  2163. // printf("NumberOfFailedServerAnnounceAllocations:\t%d\n", Statistics->NumberOfFailedServerAnnounceAllocations);
  2164. printf("NumberOfMasterAnnouncements:\t\t\t%d\n", Statistics->NumberOfDuplicateMasterAnnouncements);
  2165. printf("NumberOfIllegalDatagrams:\t\t\t%s\n", format_dlword(Statistics->NumberOfIllegalDatagrams.HighPart, Statistics->NumberOfIllegalDatagrams.LowPart, Buffer));
  2166. }
  2167. }
  2168. #define DLWBUFSIZE 22 /* buffer big enough to represent a 64-bit unsigned int
  2169. /*
  2170. * format_dlword --
  2171. *
  2172. * This function takes a 64-bit number and writes its base-10 representation
  2173. * into a string.
  2174. *
  2175. * Much magic occurs within this function, so beware. We do a lot of string-
  2176. * reversing and addition-by-hand in order to get it to work.
  2177. *
  2178. * ENTRY
  2179. * high - high 32 bits
  2180. * low - low 32 bits
  2181. * buf - buffer to put it into
  2182. *
  2183. * RETURNS
  2184. * pointer to buffer if successful
  2185. */
  2186. CHAR * format_dlword(ULONG high, ULONG low, CHAR * buf)
  2187. {
  2188. CHAR addend[DLWBUFSIZE]; /* REVERSED power of two */
  2189. CHAR copy[DLWBUFSIZE];
  2190. int i = 0;
  2191. _ultoa(low, buf, 10); /* the low part is easy */
  2192. _strrev(buf); /* and reverse it */
  2193. /* set up addend with rep. of 2^32 */
  2194. _ultoa(0xFFFFFFFF, addend, 10); /* 2^32 -1 */
  2195. _strrev(addend); /* reversed, and will stay this way */
  2196. revstr_add(addend, "1"); /* and add one == 2^32 */
  2197. /* addend will contain the reverse-ASCII base-10 rep. of 2^(i+32) */
  2198. /* now, we loop through each digit of the high longword */
  2199. while (TRUE) {
  2200. /* if this bit is set, add in its base-10 rep */
  2201. if (high & 1)
  2202. revstr_add(buf,addend);
  2203. /* move on to next bit */
  2204. high >>= 1;
  2205. /* if no more digits in high, bag out */
  2206. if (!high)
  2207. break;
  2208. /* we increment i, and double addend */
  2209. i++;
  2210. strcpy(copy, addend);
  2211. revstr_add(addend,copy); /* i.e. add it to itself */
  2212. }
  2213. _strrev(buf);
  2214. return buf;
  2215. }
  2216. /*
  2217. * revstr_add --
  2218. *
  2219. * This function will add together reversed ASCII representations of
  2220. * base-10 numbers.
  2221. *
  2222. * Examples: "2" + "2" = "4" "9" + "9" = "81"
  2223. *
  2224. * This handles arbitrarily large numbers.
  2225. *
  2226. * ENTRY
  2227. *
  2228. * source - number to add in
  2229. * target - we add source to this
  2230. *
  2231. * EXIT
  2232. * target - contains sum of entry values of source and target
  2233. *
  2234. */
  2235. VOID
  2236. revstr_add(CHAR FAR * target, CHAR FAR * source)
  2237. {
  2238. register CHAR accum;
  2239. register CHAR target_digit;
  2240. unsigned int carrybit = 0;
  2241. unsigned int srcstrlen;
  2242. unsigned int i;
  2243. srcstrlen = strlen(source);
  2244. for (i = 0; (i < srcstrlen) || carrybit; ++i) {
  2245. /* add in the source digit */
  2246. accum = (i < srcstrlen) ? (CHAR) (source[i] - '0') : (CHAR) 0;
  2247. /* add in the target digit, or '0' if we hit null term */
  2248. target_digit = target[i];
  2249. accum += (target_digit) ? target_digit : '0';
  2250. /* add in the carry bit */
  2251. accum += (CHAR) carrybit;
  2252. /* do a carry out, if necessary */
  2253. if (accum > '9') {
  2254. carrybit = 1;
  2255. accum -= 10;
  2256. }
  2257. else
  2258. carrybit = 0;
  2259. /* if we're expanding the string, must put in a new null term */
  2260. if (!target_digit)
  2261. target[i+1] = '\0';
  2262. /* and write out the digit */
  2263. target[i] = accum;
  2264. }
  2265. }
  2266. VOID
  2267. TruncateBowserLog()
  2268. {
  2269. LMDR_REQUEST_PACKET RequestPacket;
  2270. DWORD BytesReturned;
  2271. HANDLE BrowserHandle;
  2272. RtlZeroMemory(&RequestPacket, sizeof(RequestPacket));
  2273. OpenBrowser(&BrowserHandle);
  2274. RequestPacket.Version = LMDR_REQUEST_PACKET_VERSION_DOM;
  2275. RequestPacket.Parameters.Debug.TruncateLog = TRUE;
  2276. if (!DeviceIoControl(BrowserHandle, IOCTL_LMDR_DEBUG_CALL,
  2277. &RequestPacket, sizeof(RequestPacket),
  2278. NULL, 0, &BytesReturned, NULL)) {
  2279. printf("Unable to truncate browser log: %ld\n", GetLastError());
  2280. }
  2281. CloseHandle(BrowserHandle);
  2282. }
  2283. VOID
  2284. CloseBowserLog()
  2285. {
  2286. LMDR_REQUEST_PACKET RequestPacket;
  2287. DWORD BytesReturned;
  2288. HANDLE BrowserHandle;
  2289. RtlZeroMemory(&RequestPacket, sizeof(RequestPacket));
  2290. OpenBrowser(&BrowserHandle);
  2291. RequestPacket.Version = LMDR_REQUEST_PACKET_VERSION_DOM;
  2292. RequestPacket.Parameters.Debug.CloseLog = TRUE;
  2293. if (!DeviceIoControl(BrowserHandle, IOCTL_LMDR_DEBUG_CALL,
  2294. &RequestPacket, sizeof(RequestPacket),
  2295. NULL, 0, &BytesReturned, NULL)) {
  2296. printf("Unable to close browser log: %ld\n", GetLastError());
  2297. }
  2298. CloseHandle(BrowserHandle);
  2299. }
  2300. VOID
  2301. OpenBowserLog(PCHAR FileName)
  2302. {
  2303. CHAR Buffer[sizeof(LMDR_REQUEST_PACKET)+4096];
  2304. PLMDR_REQUEST_PACKET RequestPacket = (PLMDR_REQUEST_PACKET)Buffer;
  2305. DWORD BytesReturned;
  2306. HANDLE BrowserHandle;
  2307. UNICODE_STRING UString;
  2308. UNICODE_STRING NtString;
  2309. ANSI_STRING AString;
  2310. RtlZeroMemory(RequestPacket, sizeof(Buffer));
  2311. OpenBrowser(&BrowserHandle);
  2312. RtlInitString(&AString, FileName);
  2313. NtString.Buffer = NULL;
  2314. UString.Buffer = RequestPacket->Parameters.Debug.TraceFileName;
  2315. UString.MaximumLength = 4096;
  2316. RtlAnsiStringToUnicodeString(&UString, &AString, TRUE );
  2317. if (!RtlDosPathNameToNtPathName_U( UString.Buffer, &NtString, NULL, NULL )) {
  2318. printf( "Invalid file name: %ws\n", UString.Buffer );
  2319. return;
  2320. }
  2321. RtlCopyMemory( RequestPacket->Parameters.Debug.TraceFileName,
  2322. NtString.Buffer,
  2323. NtString.MaximumLength );
  2324. RequestPacket->Version = LMDR_REQUEST_PACKET_VERSION_DOM;
  2325. RequestPacket->Parameters.Debug.OpenLog = TRUE;
  2326. if (!DeviceIoControl(BrowserHandle, IOCTL_LMDR_DEBUG_CALL,
  2327. RequestPacket, sizeof(Buffer),
  2328. NULL, 0, &BytesReturned, NULL)) {
  2329. printf("Unable to open browser log: %ld\n", GetLastError());
  2330. }
  2331. if (NtString.Buffer != NULL) {
  2332. RtlFreeUnicodeString( &NtString );
  2333. }
  2334. CloseHandle(BrowserHandle);
  2335. }
  2336. VOID
  2337. SetBowserDebug(PCHAR DebugBits)
  2338. {
  2339. LMDR_REQUEST_PACKET RequestPacket;
  2340. DWORD BytesReturned;
  2341. HANDLE BrowserHandle;
  2342. char *end;
  2343. RtlZeroMemory(&RequestPacket, sizeof(RequestPacket));
  2344. OpenBrowser(&BrowserHandle);
  2345. RequestPacket.Version = LMDR_REQUEST_PACKET_VERSION_DOM;
  2346. RequestPacket.Parameters.Debug.DebugTraceBits = strtoul( DebugBits, &end, 16 );
  2347. if (!DeviceIoControl(BrowserHandle, IOCTL_LMDR_DEBUG_CALL,
  2348. &RequestPacket, sizeof(RequestPacket),
  2349. NULL, 0, &BytesReturned, NULL)) {
  2350. printf("Unable to truncate browser log: %ld\n", GetLastError());
  2351. }
  2352. CloseHandle(BrowserHandle);
  2353. }
  2354. #define NAME_MIN_LENGTH 4
  2355. #define NAME_LENGTH (CNLEN-NAME_MIN_LENGTH)
  2356. VOID
  2357. Populate(
  2358. IN BOOL PopulateDomains,
  2359. IN PCHAR Transport,
  2360. IN PCHAR Domain,
  2361. IN PCHAR EmulatedDomain,
  2362. IN PCHAR NumberOfMachinesString,
  2363. IN PCHAR PeriodicityString OPTIONAL
  2364. )
  2365. {
  2366. PSERVER_INFO_101 ServerInfo;
  2367. LPBYTE Buffer;
  2368. ULONG NumberOfMachines = strtoul(NumberOfMachinesString, NULL, 0);
  2369. ULONG Periodicity = (PeriodicityString == NULL ? 60000 : strtoul(PeriodicityString, NULL, 0));
  2370. ULONG ServerType;
  2371. WCHAR ServerComment[256];
  2372. WCHAR ComputerName[CNLEN+1];
  2373. CHAR ServerName[256];
  2374. DWORD VersionMajor;
  2375. DWORD VersionMinor;
  2376. BOOL UsedDefaultChar;
  2377. ULONG i;
  2378. BROWSE_ANNOUNCE_PACKET BrowseAnnouncement;
  2379. static char ServerCharacters[] = {"ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890.-_"};
  2380. DWORD Seed;
  2381. NET_API_STATUS Status;
  2382. UNICODE_STRING TransportName;
  2383. //
  2384. // Sanity check the transport name
  2385. //
  2386. qualify_transport(Transport, &TransportName, FALSE) ;
  2387. if (Periodicity == 0) {
  2388. Periodicity = 60000;
  2389. }
  2390. NetServerGetInfo(NULL, 101, &Buffer);
  2391. ServerInfo = (PSERVER_INFO_101 )Buffer;
  2392. ServerType = ServerInfo->sv101_type;
  2393. wcscpy(ServerComment, ServerInfo->sv101_comment);
  2394. wcscpy(ComputerName, ServerInfo->sv101_name);
  2395. VersionMajor = ServerInfo->sv101_version_major;
  2396. VersionMinor = ServerInfo->sv101_version_minor;
  2397. NetApiBufferFree(Buffer);
  2398. if (PopulateDomains) {
  2399. printf("Populating all domains on transport %s with %ld domains. Periodicity = %ld\n", Transport, NumberOfMachines, Periodicity);
  2400. } else {
  2401. printf("Populating workgroup %s on transport %s with %ld servers. Periodicity = %ld\n", Domain, Transport, NumberOfMachines, Periodicity);
  2402. }
  2403. Seed = (DWORD) time(NULL);
  2404. for (i = 0 ; i < NumberOfMachines; i += 1) {
  2405. LONG NL1 = RtlRandom(&Seed) % (NAME_LENGTH-1);
  2406. LONG NameLength;
  2407. LONG NL2;
  2408. LONG j;
  2409. NL2 = NAME_LENGTH/2 - NL1;
  2410. NameLength = NAME_LENGTH/2 + NL2 + NAME_MIN_LENGTH;
  2411. for (j = 0; j < NameLength ; j += 1) {
  2412. ServerName[j] = ServerCharacters[RtlRandom(&Seed) % (sizeof(ServerCharacters) - 1)];
  2413. }
  2414. ServerName[j] = '\0';
  2415. //
  2416. // Build an announcement packet.
  2417. //
  2418. if (PopulateDomains) {
  2419. BrowseAnnouncement.BrowseType = WkGroupAnnouncement;
  2420. } else {
  2421. BrowseAnnouncement.BrowseType = HostAnnouncement;
  2422. }
  2423. BrowseAnnouncement.BrowseAnnouncement.UpdateCount = 0;
  2424. BrowseAnnouncement.BrowseAnnouncement.Periodicity = Periodicity;
  2425. strcpy(BrowseAnnouncement.BrowseAnnouncement.ServerName, ServerName);
  2426. BrowseAnnouncement.BrowseAnnouncement.VersionMajor = (UCHAR)VersionMajor;
  2427. BrowseAnnouncement.BrowseAnnouncement.VersionMinor = (UCHAR)VersionMinor;
  2428. BrowseAnnouncement.BrowseAnnouncement.Type = (ServerType & ~(SV_TYPE_BACKUP_BROWSER | SV_TYPE_MASTER_BROWSER));
  2429. if (PopulateDomains) {
  2430. WideCharToMultiByte(CP_OEMCP, 0,
  2431. ComputerName,
  2432. wcslen(ComputerName)+1,
  2433. BrowseAnnouncement.BrowseAnnouncement.Comment,
  2434. CNLEN+1,
  2435. "?",
  2436. &UsedDefaultChar
  2437. );
  2438. } else {
  2439. WideCharToMultiByte(CP_OEMCP, 0,
  2440. ServerComment,
  2441. wcslen(ServerComment)+1,
  2442. BrowseAnnouncement.BrowseAnnouncement.Comment,
  2443. LM20_MAXCOMMENTSZ+1,
  2444. "?",
  2445. &UsedDefaultChar
  2446. );
  2447. }
  2448. BrowseAnnouncement.BrowseAnnouncement.CommentPointer = 0;
  2449. //
  2450. // Send the request
  2451. //
  2452. Status = SendDatagramA( Transport,
  2453. EmulatedDomain,
  2454. Domain,
  2455. (PopulateDomains ? DomainAnnouncement : MasterBrowser),
  2456. &BrowseAnnouncement,
  2457. sizeof(BrowseAnnouncement));
  2458. if (Status != NERR_Success) {
  2459. printf("Unable to send datagram: %ld\n", Status);
  2460. }
  2461. Sleep(50);
  2462. }
  2463. return;
  2464. }
  2465. NET_API_STATUS
  2466. GetBuildNumber(
  2467. LPWSTR Server,
  2468. LPWSTR BuildNumber
  2469. );
  2470. NET_API_STATUS
  2471. GetStatusForTransport(
  2472. IN BOOL Verbose,
  2473. IN PUNICODE_STRING Transport,
  2474. IN PUNICODE_STRING Domain
  2475. );
  2476. VOID
  2477. BrowserStatus(
  2478. IN BOOL Verbose,
  2479. IN PCHAR Domain OPTIONAL
  2480. )
  2481. {
  2482. NET_API_STATUS Status;
  2483. UNICODE_STRING DomainName;
  2484. PVOID Buffer;
  2485. PWKSTA_INFO_101 WkstaInfo;
  2486. PLMDR_TRANSPORT_LIST TransportList, TransportEntry;
  2487. if (Domain == NULL) {
  2488. PWCHAR DomainBuffer = NULL;
  2489. UNICODE_STRING TDomainName;
  2490. Status = NetWkstaGetInfo(NULL, 101, (LPBYTE *)&Buffer);
  2491. if (Status != NERR_Success) {
  2492. printf("Unable to retrieve workstation information: %s\n", get_error_text(Status));
  2493. exit(Status);
  2494. }
  2495. WkstaInfo = (PWKSTA_INFO_101 )Buffer;
  2496. DomainBuffer = malloc((wcslen(WkstaInfo->wki101_langroup)+1)*sizeof(WCHAR));
  2497. if ( DomainBuffer == NULL) {
  2498. printf("Not enough memory\n");
  2499. exit( ERROR_NOT_ENOUGH_MEMORY );
  2500. }
  2501. DomainName.Buffer = DomainBuffer;
  2502. DomainName.MaximumLength = (wcslen(WkstaInfo->wki101_langroup)+1)*sizeof(WCHAR);
  2503. RtlInitUnicodeString(&TDomainName, WkstaInfo->wki101_langroup);
  2504. RtlCopyUnicodeString(&DomainName, &TDomainName);
  2505. NetApiBufferFree(Buffer);
  2506. } else {
  2507. ANSI_STRING AString;
  2508. RtlInitAnsiString(&AString, Domain);
  2509. RtlAnsiStringToUnicodeString(&DomainName, &AString, TRUE);
  2510. }
  2511. //
  2512. // We now know the domain to query. Iterate through the transports and
  2513. // get status for each of them.
  2514. //
  2515. Status = GetBrowserTransportList(&TransportList);
  2516. if (Status != NERR_Success) {
  2517. printf("Unable to retrieve transport list: %s\n", get_error_text(Status));
  2518. exit(Status);
  2519. }
  2520. TransportEntry = TransportList;
  2521. while (TransportEntry != NULL) {
  2522. UNICODE_STRING TransportName;
  2523. TransportName.Buffer = TransportEntry->TransportName;
  2524. TransportName.Length = (USHORT)TransportEntry->TransportNameLength;
  2525. TransportName.MaximumLength = (USHORT)TransportEntry->TransportNameLength;
  2526. Status = GetStatusForTransport(Verbose, &TransportName, &DomainName);
  2527. if (TransportEntry->NextEntryOffset == 0) {
  2528. TransportEntry = NULL;
  2529. } else {
  2530. TransportEntry = (PLMDR_TRANSPORT_LIST)((PCHAR)TransportEntry+TransportEntry->NextEntryOffset);
  2531. }
  2532. }
  2533. NetApiBufferFree(TransportList);
  2534. exit(0);
  2535. }
  2536. VOID
  2537. DumpTransportList(
  2538. VOID
  2539. )
  2540. {
  2541. NET_API_STATUS Status;
  2542. PLMDR_TRANSPORT_LIST TransportList, TransportEntry;
  2543. ULONG TransportNumber = 1;
  2544. printf("\nList of transports currently bound to the browser\n\n" );
  2545. //
  2546. // We now know the domain to query. Iterate through the transports and
  2547. // get status for each of them.
  2548. //
  2549. Status = GetBrowserTransportList(&TransportList);
  2550. if (Status != NERR_Success) {
  2551. printf("Unable to retrieve transport list: %s\n", get_error_text(Status));
  2552. exit(Status);
  2553. }
  2554. TransportEntry = TransportList;
  2555. while (TransportEntry != NULL) {
  2556. UNICODE_STRING TransportName;
  2557. TransportName.Buffer = TransportEntry->TransportName;
  2558. TransportName.Length = (USHORT)TransportEntry->TransportNameLength;
  2559. TransportName.MaximumLength = (USHORT)TransportEntry->TransportNameLength;
  2560. printf("%6.0d %-16.16wZ\n", TransportNumber, &TransportName );
  2561. TransportNumber ++;
  2562. if (TransportEntry->NextEntryOffset == 0) {
  2563. TransportEntry = NULL;
  2564. } else {
  2565. TransportEntry = (PLMDR_TRANSPORT_LIST)((PCHAR)TransportEntry+TransportEntry->NextEntryOffset);
  2566. }
  2567. }
  2568. NetApiBufferFree(TransportList);
  2569. }
  2570. NET_API_STATUS
  2571. GetBrowserTransportList(
  2572. OUT PLMDR_TRANSPORT_LIST *TransportList
  2573. )
  2574. /*++
  2575. Routine Description:
  2576. This routine returns the list of transports bound into the browser.
  2577. Arguments:
  2578. OUT PLMDR_TRANSPORT_LIST *TransportList - Transport list to return.
  2579. Return Value:
  2580. NET_API_STATUS - NERR_Success or reason for failure.
  2581. --*/
  2582. {
  2583. NET_API_STATUS Status;
  2584. HANDLE BrowserHandle;
  2585. LMDR_REQUEST_PACKET RequestPacket;
  2586. Status = OpenBrowser(&BrowserHandle);
  2587. if (Status != NERR_Success) {
  2588. return Status;
  2589. }
  2590. RequestPacket.Version = LMDR_REQUEST_PACKET_VERSION_DOM;
  2591. RequestPacket.Type = EnumerateXports;
  2592. RtlInitUnicodeString(&RequestPacket.TransportName, NULL);
  2593. RtlInitUnicodeString(&RequestPacket.EmulatedDomainName, NULL);
  2594. Status = DeviceControlGetInfo(
  2595. BrowserHandle,
  2596. IOCTL_LMDR_ENUMERATE_TRANSPORTS,
  2597. &RequestPacket,
  2598. sizeof(RequestPacket),
  2599. (PVOID *)TransportList,
  2600. 0xffffffff,
  2601. 4096,
  2602. NULL);
  2603. NtClose(BrowserHandle);
  2604. return Status;
  2605. }
  2606. NET_API_STATUS
  2607. GetStatusForTransport(
  2608. IN BOOL Verbose,
  2609. IN PUNICODE_STRING Transport,
  2610. IN PUNICODE_STRING Domain
  2611. )
  2612. {
  2613. WCHAR MasterName[256];
  2614. WCHAR MasterServerName[256+2];
  2615. NET_API_STATUS Status;
  2616. PVOID Buffer;
  2617. PSERVER_INFO_101 ServerInfo;
  2618. DWORD EntriesInList;
  2619. DWORD TotalEntries;
  2620. DWORD BrowserListLength;
  2621. PWSTR *BrowserList;
  2622. DWORD i;
  2623. DWORD NumberNTASMachines = 0;
  2624. DWORD NumberOS2DCs = 0;
  2625. DWORD NumberWfWMachines = 0;
  2626. DWORD NumberOfNTMachines = 0;
  2627. DWORD NumberWfWBrowsers = 0;
  2628. DWORD NumberOfOs2Machines = 0;
  2629. DWORD NumberOfBrowsers = 0;
  2630. DWORD NumberOfBackupBrowsers = 0;
  2631. DWORD NumberOfMasterBrowsers = 0;
  2632. WCHAR BuildNumber[512];
  2633. printf("\n\nStatus for domain %s on transport %s\n", UnicodeToPrintfString(Domain->Buffer), UnicodeToPrintfString2(Transport->Buffer));
  2634. Status = GetBrowserServerList(Transport, Domain->Buffer, &BrowserList, &BrowserListLength, TRUE);
  2635. if (Status == NERR_Success) {
  2636. printf(" Browsing is active on domain.\n");
  2637. } else {
  2638. printf(" Browsing is NOT active on domain. Status : %ld\n", Status);
  2639. Status = GetNetBiosMasterName(
  2640. Transport->Buffer,
  2641. Domain->Buffer,
  2642. MasterName,
  2643. NULL);
  2644. if (Status == NERR_Success) {
  2645. wcscpy(MasterServerName, L"\\\\");
  2646. wcscat(MasterServerName, MasterName);
  2647. printf(" Master browser name is held by: %s\n", UnicodeToPrintfString(MasterName));
  2648. Status = GetBuildNumber(MasterServerName, BuildNumber);
  2649. if (Status == NERR_Success) {
  2650. printf(" Master browser is running build %s\n", UnicodeToPrintfString(BuildNumber));
  2651. } else {
  2652. PSERVER_INFO_101 pSV101;
  2653. printf(" Unable to determine build of browser master: %d\n", Status);
  2654. Status = NetServerGetInfo(MasterServerName, 101, (LPBYTE *)&pSV101);
  2655. if (Status != NERR_Success) {
  2656. printf(" Unable to determine server information for browser master: %d\n", Status);
  2657. return Status;
  2658. }
  2659. printf(" %-16.16s. Version:%2.2d.%2.2d Flags: %lx ", UnicodeToPrintfString(MasterServerName), pSV101->sv101_version_major, pSV101->sv101_version_minor, pSV101->sv101_type);
  2660. if (pSV101->sv101_type & SV_TYPE_WFW) {
  2661. printf("WFW ");
  2662. }
  2663. if (pSV101->sv101_type & SV_TYPE_NT) {
  2664. printf("NT ");
  2665. }
  2666. if (pSV101->sv101_type & SV_TYPE_POTENTIAL_BROWSER) {
  2667. printf("POTENTIAL ");
  2668. }
  2669. if (pSV101->sv101_type & SV_TYPE_BACKUP_BROWSER) {
  2670. printf("BACKUP ");
  2671. }
  2672. if (pSV101->sv101_type & SV_TYPE_MASTER_BROWSER) {
  2673. printf("MASTER ");
  2674. }
  2675. if (pSV101->sv101_type & SV_TYPE_DOMAIN_CTRL) {
  2676. printf("CONTROLLER ");
  2677. }
  2678. if (pSV101->sv101_type & SV_TYPE_DOMAIN_BAKCTRL) {
  2679. printf("BACKUP CONTROLLER ");
  2680. }
  2681. if (pSV101->sv101_type & SV_TYPE_SERVER_NT) {
  2682. printf("SERVER ");
  2683. }
  2684. }
  2685. } else {
  2686. printf(" Master name cannot be determined from GetAdapterStatus.\n");
  2687. }
  2688. return Status;
  2689. }
  2690. Status = GetNetBiosMasterName(
  2691. Transport->Buffer,
  2692. Domain->Buffer,
  2693. MasterName,
  2694. NULL);
  2695. if (Status == NERR_Success) {
  2696. wcscpy(MasterServerName, L"\\\\");
  2697. wcscat(MasterServerName, MasterName);
  2698. printf(" Master browser name is: %s\n", UnicodeToPrintfString(MasterName));
  2699. } else {
  2700. printf(" Master name cannot be determined from GetAdapterStatus. Using %s\n", UnicodeToPrintfString(BrowserList[0]));
  2701. wcscpy(MasterServerName, BrowserList[0]);
  2702. wcscpy(MasterName, (BrowserList[0])+2);
  2703. }
  2704. //
  2705. // Print the build number or whatever else you can find out about the master
  2706. //
  2707. Status = GetBuildNumber(MasterServerName, BuildNumber);
  2708. if (Status == NERR_Success) {
  2709. printf(" Master browser is running build %s\n", UnicodeToPrintfString(BuildNumber));
  2710. } else {
  2711. PSERVER_INFO_101 pSV101;
  2712. printf(" Unable to determine build of browser master: %d\n", Status);
  2713. Status = NetServerGetInfo(MasterServerName, 101, (LPBYTE *)&pSV101);
  2714. if (Status != NERR_Success) {
  2715. printf(" Unable to determine server information for browser master: %d\n", Status);
  2716. }
  2717. if (Status == NERR_Success) {
  2718. printf(" \\\\%-16.16s. Version:%2.2d.%2.2d Flags: %lx ", UnicodeToPrintfString(MasterServerName), pSV101->sv101_version_major, pSV101->sv101_version_minor, pSV101->sv101_type);
  2719. if (pSV101->sv101_type & SV_TYPE_WFW) {
  2720. printf("WFW ");
  2721. }
  2722. if (pSV101->sv101_type & SV_TYPE_NT) {
  2723. printf("NT ");
  2724. }
  2725. if (pSV101->sv101_type & SV_TYPE_POTENTIAL_BROWSER) {
  2726. printf("POTENTIAL ");
  2727. }
  2728. if (pSV101->sv101_type & SV_TYPE_BACKUP_BROWSER) {
  2729. printf("BACKUP ");
  2730. }
  2731. if (pSV101->sv101_type & SV_TYPE_MASTER_BROWSER) {
  2732. printf("MASTER ");
  2733. }
  2734. if (pSV101->sv101_type & SV_TYPE_DOMAIN_CTRL) {
  2735. printf("CONTROLLER ");
  2736. }
  2737. if (pSV101->sv101_type & SV_TYPE_DOMAIN_BAKCTRL) {
  2738. printf("BACKUP CONTROLLER ");
  2739. }
  2740. if (pSV101->sv101_type & SV_TYPE_SERVER_NT) {
  2741. printf("SERVER ");
  2742. }
  2743. printf("\n");
  2744. }
  2745. }
  2746. printf(" %ld backup servers retrieved from master %s\n", BrowserListLength, UnicodeToPrintfString(MasterName));
  2747. for (i = 0; i < BrowserListLength ; i++ ) {
  2748. printf(" %s\n", UnicodeToPrintfString(BrowserList[i]));
  2749. }
  2750. Status = RxNetServerEnum(MasterServerName,
  2751. Transport->Buffer,
  2752. 101,
  2753. (LPBYTE *)&Buffer,
  2754. 0xffffffff, // PreferedMaxLength
  2755. &EntriesInList,
  2756. &TotalEntries,
  2757. SV_TYPE_ALL,
  2758. // Domain->Buffer,
  2759. NULL,
  2760. NULL
  2761. );
  2762. if (Status != NERR_Success) {
  2763. printf(" Unable to retrieve server list from %s: %ld\n", UnicodeToPrintfString(MasterName), Status);
  2764. return Status;
  2765. } else {
  2766. printf(" There are %ld servers in domain %s on transport %s\n", EntriesInList, UnicodeToPrintfString(Domain->Buffer), UnicodeToPrintfString2(Transport->Buffer));
  2767. if (Verbose) {
  2768. if (EntriesInList != 0) {
  2769. ServerInfo = (PSERVER_INFO_101)Buffer;
  2770. for (i = 0 ; i < EntriesInList ; i += 1) {
  2771. if (ServerInfo->sv101_type & (SV_TYPE_DOMAIN_BAKCTRL | SV_TYPE_DOMAIN_CTRL)) {
  2772. if (ServerInfo->sv101_type & SV_TYPE_NT) {
  2773. NumberNTASMachines += 1;
  2774. } else {
  2775. NumberOS2DCs += 1;
  2776. }
  2777. }
  2778. if (ServerInfo->sv101_type & SV_TYPE_WFW) {
  2779. NumberWfWMachines += 1;
  2780. if (ServerInfo->sv101_type & (SV_TYPE_BACKUP_BROWSER | SV_TYPE_POTENTIAL_BROWSER | SV_TYPE_MASTER_BROWSER)) {
  2781. NumberWfWBrowsers += 1;
  2782. }
  2783. } else if (ServerInfo->sv101_type & SV_TYPE_NT) {
  2784. NumberOfNTMachines += 1;
  2785. } else {
  2786. NumberOfOs2Machines += 1;
  2787. }
  2788. if (ServerInfo->sv101_type & (SV_TYPE_BACKUP_BROWSER | SV_TYPE_POTENTIAL_BROWSER | SV_TYPE_MASTER_BROWSER)) {
  2789. NumberOfBrowsers += 1;
  2790. if (ServerInfo->sv101_type & SV_TYPE_BACKUP_BROWSER) {
  2791. NumberOfBackupBrowsers += 1;
  2792. }
  2793. if (ServerInfo->sv101_type & SV_TYPE_MASTER_BROWSER) {
  2794. NumberOfMasterBrowsers += 1;
  2795. }
  2796. }
  2797. ServerInfo += 1;
  2798. }
  2799. printf(" Number of NT Advanced Servers:\t\t\t%ld\n", NumberNTASMachines);
  2800. printf(" Number of OS/2 Domain controllers:\t\t%ld\n", NumberOS2DCs);
  2801. printf(" Number of Windows For Workgroups machines:\t%ld\n", NumberWfWMachines);
  2802. printf(" Number of Os/2 machines:\t\t\t%ld\n", NumberOfOs2Machines);
  2803. printf(" Number of NT machines:\t\t\t\t%ld\n", NumberOfNTMachines);
  2804. printf("\n");
  2805. printf(" Number of active WfW browsers:\t\t\t%ld\n", NumberWfWBrowsers);
  2806. printf(" Number of browsers:\t\t\t\t%ld\n", NumberOfBrowsers);
  2807. printf(" Number of backup browsers:\t\t\t%ld\n", NumberOfBackupBrowsers);
  2808. printf(" Number of master browsers:\t\t\t%ld\n", NumberOfMasterBrowsers);
  2809. }
  2810. }
  2811. }
  2812. Status = RxNetServerEnum(MasterServerName,
  2813. Transport->Buffer,
  2814. 101,
  2815. (LPBYTE *)&Buffer,
  2816. 0xffffffff, // PreferedMaxLength
  2817. &EntriesInList,
  2818. &TotalEntries,
  2819. SV_TYPE_DOMAIN_ENUM,
  2820. // Domain->Buffer,
  2821. NULL,
  2822. NULL
  2823. );
  2824. if ( Status == ERROR_MORE_DATA ) {
  2825. printf(" Only %ld out of %ld domains could be returned\n", EntriesInList, TotalEntries );
  2826. } else if (Status != NERR_Success) {
  2827. printf(" Unable to retrieve server list from %s: %ld\n", UnicodeToPrintfString(MasterName), Status);
  2828. return Status;
  2829. }
  2830. printf(" There are %ld domains in domain %s on transport %s\n", EntriesInList, UnicodeToPrintfString(Domain->Buffer), UnicodeToPrintfString2(Transport->Buffer));
  2831. return NERR_Success;
  2832. }
  2833. #define BUILD_NUMBER_KEY L"SOFTWARE\\MICROSOFT\\WINDOWS NT\\CURRENTVERSION"
  2834. #define BUILD_NUMBER_BUFFER_LENGTH 80
  2835. NET_API_STATUS
  2836. GetBuildNumber(
  2837. LPWSTR Server,
  2838. LPWSTR BuildNumber
  2839. )
  2840. {
  2841. HKEY RegKey;
  2842. HKEY RegKeyBuildNumber;
  2843. DWORD WinStatus;
  2844. DWORD BuildNumberLength;
  2845. DWORD KeyType;
  2846. WinStatus = RegConnectRegistry(Server, HKEY_LOCAL_MACHINE,
  2847. &RegKey);
  2848. if (WinStatus == RPC_S_SERVER_UNAVAILABLE) {
  2849. // printf("%15ws no longer accessable", Server+2);
  2850. return(WinStatus);
  2851. }
  2852. else if (WinStatus != ERROR_SUCCESS) {
  2853. printf("Could not connect to registry, error = %d", WinStatus);
  2854. return(WinStatus);
  2855. }
  2856. WinStatus = RegOpenKeyEx(RegKey, BUILD_NUMBER_KEY,0, KEY_READ,
  2857. & RegKeyBuildNumber);
  2858. if (WinStatus != ERROR_SUCCESS) {
  2859. printf("Could not open key in registry, error = %d", WinStatus);
  2860. return(WinStatus);
  2861. }
  2862. BuildNumberLength = BUILD_NUMBER_BUFFER_LENGTH * sizeof(WCHAR);
  2863. WinStatus = RegQueryValueEx(RegKeyBuildNumber, L"CurrentBuildNumber",
  2864. (LPDWORD) NULL, & KeyType, (LPBYTE) BuildNumber, & BuildNumberLength);
  2865. if (WinStatus != ERROR_SUCCESS) {
  2866. WinStatus = RegQueryValueEx(RegKeyBuildNumber, L"CurrentBuild",
  2867. (LPDWORD) NULL, & KeyType, (LPBYTE) BuildNumber, & BuildNumberLength);
  2868. if (WinStatus != ERROR_SUCCESS) {
  2869. RegCloseKey(RegKeyBuildNumber);
  2870. RegCloseKey(RegKey);
  2871. return WinStatus;
  2872. }
  2873. }
  2874. WinStatus = RegCloseKey(RegKeyBuildNumber);
  2875. if (WinStatus != ERROR_SUCCESS) {
  2876. printf("Could not close registry key, error = %d", WinStatus);
  2877. }
  2878. WinStatus = RegCloseKey(RegKey);
  2879. if (WinStatus != ERROR_SUCCESS) {
  2880. printf("Could not close registry connection, error = %d", WinStatus);
  2881. }
  2882. return(WinStatus);
  2883. }
  2884. NET_API_STATUS
  2885. GetNetBiosPdcName(
  2886. IN LPWSTR NetworkName,
  2887. IN LPWSTR PrimaryDomain,
  2888. OUT LPWSTR MasterName
  2889. );
  2890. VOID
  2891. GetPdc(
  2892. IN PCHAR Transport,
  2893. IN PCHAR Domain
  2894. )
  2895. {
  2896. NET_API_STATUS Status;
  2897. UNICODE_STRING TransportName;
  2898. ANSI_STRING AString;
  2899. WCHAR MasterName[256];
  2900. UNICODE_STRING DomainName;
  2901. qualify_transport(Transport, &TransportName, FALSE ) ;
  2902. RtlInitString(&AString, Domain);
  2903. RtlAnsiStringToUnicodeString(&DomainName, &AString, TRUE);
  2904. Status = GetNetBiosPdcName(TransportName.Buffer, DomainName.Buffer, MasterName);
  2905. if (Status != NERR_Success) {
  2906. printf("Unable to get PDC: %s\n", get_error_text(Status));
  2907. exit(1);
  2908. }
  2909. printf("PDC: %s\n", UnicodeToPrintfString(MasterName));
  2910. }
  2911. NET_API_STATUS
  2912. GetNetBiosPdcName(
  2913. IN LPWSTR NetworkName,
  2914. IN LPWSTR PrimaryDomain,
  2915. OUT LPWSTR MasterName
  2916. )
  2917. {
  2918. CCHAR LanaNum;
  2919. NCB AStatNcb;
  2920. struct {
  2921. ADAPTER_STATUS AdapterInfo;
  2922. NAME_BUFFER Names[32];
  2923. } AdapterStatus;
  2924. WORD i;
  2925. CHAR remoteName[CNLEN+1];
  2926. NET_API_STATUS Status;
  2927. BOOL UsedDefaultChar;
  2928. Status = BrGetLanaNumFromNetworkName(NetworkName, &LanaNum);
  2929. if (Status != NERR_Success) {
  2930. return Status;
  2931. }
  2932. ClearNcb(&AStatNcb)
  2933. AStatNcb.ncb_command = NCBRESET;
  2934. AStatNcb.ncb_lsn = 0; // Request resources
  2935. AStatNcb.ncb_lana_num = LanaNum;
  2936. AStatNcb.ncb_callname[0] = 0; // 16 sessions
  2937. AStatNcb.ncb_callname[1] = 0; // 16 commands
  2938. AStatNcb.ncb_callname[2] = 0; // 8 names
  2939. AStatNcb.ncb_callname[3] = 0; // Don't want the reserved address
  2940. Netbios( &AStatNcb );
  2941. ClearNcb( &AStatNcb );
  2942. if (WideCharToMultiByte( CP_OEMCP, 0,
  2943. PrimaryDomain,
  2944. -1,
  2945. remoteName,
  2946. sizeof(remoteName),
  2947. "?",
  2948. &UsedDefaultChar) == 0) {
  2949. return GetLastError();
  2950. }
  2951. //
  2952. // Uppercase the remote name.
  2953. //
  2954. _strupr(remoteName);
  2955. AStatNcb.ncb_command = NCBASTAT;
  2956. RtlCopyMemory( AStatNcb.ncb_callname, remoteName, strlen(remoteName));
  2957. AStatNcb.ncb_callname[15] = PRIMARY_CONTROLLER_SIGNATURE;
  2958. AStatNcb.ncb_lana_num = LanaNum;
  2959. AStatNcb.ncb_length = sizeof( AdapterStatus );
  2960. AStatNcb.ncb_buffer = (CHAR *)&AdapterStatus;
  2961. Netbios( &AStatNcb );
  2962. if ( AStatNcb.ncb_retcode == NRC_GOODRET ) {
  2963. for ( i=0 ; i < AdapterStatus.AdapterInfo.name_count ; i++ ) {
  2964. if (AdapterStatus.Names[i].name[NCBNAMSZ-1] == SERVER_SIGNATURE) {
  2965. // LPWSTR SpacePointer;
  2966. DWORD j;
  2967. if (MultiByteToWideChar(CP_OEMCP,
  2968. 0,
  2969. AdapterStatus.Names[i].name,
  2970. CNLEN,
  2971. MasterName,
  2972. CNLEN) == 0) {
  2973. return(GetLastError());
  2974. }
  2975. for (j = CNLEN - 1; j ; j -= 1) {
  2976. if (MasterName[j] != L' ') {
  2977. MasterName[j+1] = UNICODE_NULL;
  2978. break;
  2979. }
  2980. }
  2981. return NERR_Success;
  2982. }
  2983. }
  2984. return AStatNcb.ncb_retcode;
  2985. } else {
  2986. return AStatNcb.ncb_retcode;
  2987. }
  2988. }
  2989. VOID
  2990. DisplayServerInfo101(
  2991. PSERVER_INFO_101 Server,
  2992. BOOL DomainEnumeration
  2993. )
  2994. {
  2995. DWORD MajorVersion, MinorVersion ;
  2996. DWORD CharactersPrinted = 0;
  2997. if ( DomainEnumeration ) {
  2998. printf( "%-16.16ws", Server->sv101_name);
  2999. CharactersPrinted += 16;
  3000. } else {
  3001. printf( "\\\\%-16.16ws", Server->sv101_name);
  3002. CharactersPrinted += 18;
  3003. }
  3004. printf(" %s",
  3005. (Server->sv101_platform_id == PLATFORM_ID_DOS ? "DOS" :
  3006. (Server->sv101_platform_id == PLATFORM_ID_OS2 ?
  3007. ((Server->sv101_type & SV_TYPE_WINDOWS) ? "W95" :
  3008. ((Server->sv101_type & SV_TYPE_WFW) ? "WFW": "OS2" )) :
  3009. (Server->sv101_platform_id == PLATFORM_ID_NT ? "NT " :
  3010. "Unk") ) ) );
  3011. CharactersPrinted += 5;
  3012. MajorVersion = Server->sv101_version_major ;
  3013. MinorVersion = Server->sv101_version_minor ;
  3014. if ((MajorVersion == 1) && (MinorVersion >= 50)) {
  3015. printf(" %2.2d.%2.2d", MajorVersion+2, MinorVersion-40);
  3016. } else {
  3017. printf(" %2.2d.%2.2d", MajorVersion, MinorVersion);
  3018. }
  3019. CharactersPrinted += 5;
  3020. CharactersPrinted += display_sv_bits(Server->sv101_type);
  3021. if ( Server->sv101_comment != NULL && wcslen(Server->sv101_comment) > 0 ) {
  3022. printf( " " );
  3023. CharactersPrinted ++;
  3024. while ( CharactersPrinted < 48 ) {
  3025. printf( " " );
  3026. CharactersPrinted ++;
  3027. }
  3028. while ( CharactersPrinted % 4 != 0 ) {
  3029. printf( " " );
  3030. CharactersPrinted ++;
  3031. }
  3032. printf( "%ws", Server->sv101_comment );
  3033. }
  3034. }
  3035. //
  3036. // display server bits as defined in BitsToStringTable
  3037. //
  3038. // Returns the number of characters printed.
  3039. DWORD
  3040. display_sv_bits(DWORD dwBits)
  3041. {
  3042. BIT_NAME *lpEntry = BitToStringTable ;
  3043. BOOL fFirst = TRUE ;
  3044. DWORD CharactersPrinted = 0;
  3045. printf(" (") ;
  3046. CharactersPrinted += 2;
  3047. while (1)
  3048. {
  3049. if (lpEntry->dwValue & dwBits)
  3050. {
  3051. if (lpEntry != BitToStringTable && !fFirst) {
  3052. printf(",") ;
  3053. CharactersPrinted += 1;
  3054. }
  3055. dwBits &= ~lpEntry->dwValue;
  3056. printf("%s",lpEntry->lpString) ;
  3057. CharactersPrinted += strlen(lpEntry->lpString);
  3058. fFirst = FALSE ;
  3059. }
  3060. lpEntry++ ;
  3061. if ( !(lpEntry->dwValue) ) {
  3062. dwBits &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
  3063. if ( dwBits != 0 ) {
  3064. if ( !fFirst ) {
  3065. printf(",") ;
  3066. CharactersPrinted += 1;
  3067. }
  3068. printf( "%8.8X", dwBits );
  3069. CharactersPrinted += 8;
  3070. }
  3071. printf(")") ;
  3072. CharactersPrinted += 1;
  3073. break ;
  3074. }
  3075. }
  3076. return CharactersPrinted;
  3077. }
  3078. //
  3079. // map an error number to its error message string. note, uses static,
  3080. // not reentrant.
  3081. //
  3082. CHAR *
  3083. get_error_text(DWORD dwErr)
  3084. {
  3085. static CHAR text[512] ;
  3086. WORD err ;
  3087. WORD msglen ;
  3088. memset(text,0, sizeof(text));
  3089. //
  3090. // get error message
  3091. //
  3092. err = DosGetMessage(NULL,
  3093. 0,
  3094. text,
  3095. sizeof(text),
  3096. (WORD)dwErr,
  3097. (dwErr<NERR_BASE)||(dwErr>MAX_LANMAN_MESSAGE_ID) ?
  3098. TEXT("BASE"):TEXT("NETMSG"),
  3099. &msglen) ;
  3100. if (err != NERR_Success)
  3101. {
  3102. // use number instead. if looks like NTSTATUS then use hex.
  3103. sprintf(text, (dwErr & 0xC0000000)?"(%lx)":"(%ld)", dwErr) ;
  3104. }
  3105. return text ;
  3106. }
  3107. BOOL
  3108. look_for_help(int argc, char **argv)
  3109. {
  3110. int i ;
  3111. for (i = 2; i < argc; i++)
  3112. {
  3113. if (_stricmp(argv[i],"/help") == 0)
  3114. return TRUE ;
  3115. if (_stricmp(argv[i],"-help") == 0)
  3116. return TRUE ;
  3117. if (strcmp(argv[i],"/?") == 0)
  3118. return TRUE ;
  3119. if (strcmp(argv[i],"-?") == 0)
  3120. return TRUE ;
  3121. }
  3122. return FALSE ;
  3123. }
  3124. CHAR
  3125. PrintfBuffer[256];
  3126. PCHAR
  3127. UnicodeToPrintfString(
  3128. PWCHAR WideChar
  3129. )
  3130. {
  3131. UNICODE_STRING UString;
  3132. ANSI_STRING AString;
  3133. AString.Buffer = PrintfBuffer;
  3134. AString.MaximumLength = sizeof(PrintfBuffer);
  3135. RtlInitUnicodeString(&UString, WideChar);
  3136. RtlUnicodeStringToOemString(&AString, &UString, FALSE);
  3137. return PrintfBuffer;
  3138. }
  3139. CHAR
  3140. PrintfBuffer2[256];
  3141. PCHAR
  3142. UnicodeToPrintfString2(
  3143. PWCHAR WideChar
  3144. )
  3145. {
  3146. UNICODE_STRING UString;
  3147. ANSI_STRING AString;
  3148. AString.Buffer = PrintfBuffer2;
  3149. AString.MaximumLength = sizeof(PrintfBuffer2);
  3150. RtlInitUnicodeString(&UString, WideChar);
  3151. RtlUnicodeStringToOemString(&AString, &UString, FALSE);
  3152. return PrintfBuffer2;
  3153. }
  3154. VOID
  3155. GetWinsServer(
  3156. IN PCHAR Transport
  3157. )
  3158. {
  3159. NET_API_STATUS Status;
  3160. UNICODE_STRING TransportName;
  3161. LPTSTR PrimaryWinsServerAddress;
  3162. LPTSTR SecondaryWinsServerAddress;
  3163. qualify_transport(Transport, &TransportName, FALSE) ;
  3164. Status = BrGetWinsServerName(&TransportName, &PrimaryWinsServerAddress, &SecondaryWinsServerAddress);
  3165. if (Status != NERR_Success) {
  3166. printf("Unable to query WINS server address: %ld\n", Status);
  3167. exit(1);
  3168. }
  3169. printf("Primary Wins server address: %ws\n", PrimaryWinsServerAddress);
  3170. printf("Secondary Wins server address: %ws\n", SecondaryWinsServerAddress);
  3171. exit(0);
  3172. }
  3173. VOID
  3174. GetDomainList(
  3175. IN PCHAR IpAddress
  3176. )
  3177. {
  3178. NET_API_STATUS Status;
  3179. PSERVER_INFO_101 WinsServerList;
  3180. DWORD EntriesInList;
  3181. DWORD TotalEntriesInList;
  3182. UNICODE_STRING IpAddressString;
  3183. ANSI_STRING IpAddressAString;
  3184. DWORD i;
  3185. RtlInitString(&IpAddressAString, IpAddress);
  3186. RtlAnsiStringToUnicodeString(&IpAddressString, &IpAddressAString, TRUE);
  3187. Status = BrQuerySpecificWinsServer(IpAddressString.Buffer, &WinsServerList, &EntriesInList, &TotalEntriesInList);
  3188. if (Status != NERR_Success) {
  3189. printf("Unable to query domain list from WINS server: %ld\n", Status);
  3190. exit(1);
  3191. }
  3192. PrepareServerListForMerge( WinsServerList, 101, EntriesInList );
  3193. for (i = 0; i < EntriesInList ; i ++ ) {
  3194. printf("%-16.16s\n", UnicodeToPrintfString(WinsServerList[i].sv101_name));
  3195. }
  3196. exit(0);
  3197. }
  3198. NET_API_STATUS
  3199. BrMapStatus(
  3200. IN NTSTATUS Status
  3201. )
  3202. {
  3203. return RtlNtStatusToDosError(Status);
  3204. }
  3205. VOID
  3206. EnumEmulatedDomains(
  3207. )
  3208. /*++
  3209. Routine Description:
  3210. Enumerate emulated domains.
  3211. Arguments:
  3212. None.
  3213. Return Value:
  3214. None.
  3215. --*/
  3216. {
  3217. NET_API_STATUS NetStatus;
  3218. LPWSTR EmulatedDomainName;
  3219. LPWSTR EmulatedComputerName;
  3220. DWORD RoleBits;
  3221. PBROWSER_EMULATED_DOMAIN Domains;
  3222. DWORD EntriesRead;
  3223. DWORD i;
  3224. //
  3225. // Enumerate the emulated domains.
  3226. //
  3227. NetStatus = I_BrowserQueryEmulatedDomains(
  3228. NULL,
  3229. &Domains,
  3230. &EntriesRead );
  3231. if ( NetStatus != NERR_Success ) {
  3232. printf( "Can't enumerate EmulatedDomains: %s\n", get_error_text(NetStatus) );
  3233. return;
  3234. }
  3235. if ( EntriesRead == 0 ) {
  3236. printf( "There are no emulated domains\n" );
  3237. return;
  3238. }
  3239. //
  3240. // Print the enumerated information
  3241. //
  3242. for ( i=0 ; i<EntriesRead; i++ ) {
  3243. printf( "%-16.16ws %3.3s \\\\%-16.16ws\n",
  3244. Domains[i].DomainName,
  3245. (Domains[i].Role & BROWSER_ROLE_PDC) ? "PDC" : "BDC",
  3246. Domains[i].EmulatedServerName );
  3247. }
  3248. }
  3249. VOID
  3250. SetEmulatedDomain(
  3251. IN PCHAR EmulatedDomain,
  3252. IN PCHAR Role,
  3253. IN PCHAR EmulatedComputer
  3254. )
  3255. /*++
  3256. Routine Description:
  3257. Create and/or set role on emulated domain
  3258. Arguments:
  3259. EmulatedDomain - Emulated Domain name.
  3260. Role - Role this machine plays in the domain.
  3261. EmulatedComputerName - Name of this computer in the emulated domain.
  3262. (Need only be specified when the domain is being created.)
  3263. Return Value:
  3264. NET_API_STATUS - NERR_Success or reason for failure.
  3265. --*/
  3266. {
  3267. NET_API_STATUS NetStatus;
  3268. LPWSTR EmulatedDomainName;
  3269. LPWSTR EmulatedComputerName;
  3270. DWORD RoleBits;
  3271. //
  3272. // Comvert strings to unicode.
  3273. //
  3274. EmulatedDomainName = NetpAllocWStrFromStr( EmulatedDomain );
  3275. if ( EmulatedComputer != NULL ) {
  3276. EmulatedComputerName = NetpAllocWStrFromStr( EmulatedComputer );
  3277. } else {
  3278. EmulatedComputerName = NULL;
  3279. }
  3280. //
  3281. // Convert Role to binary
  3282. //
  3283. if ( _stricmp( Role, "PDC") == 0 ) {
  3284. RoleBits = BROWSER_ROLE_PDC;
  3285. } else if ( _stricmp( Role, "BDC") == 0 ) {
  3286. RoleBits = BROWSER_ROLE_BDC;
  3287. } else if ( _strnicmp( Role, "DELETE", 3) == 0 ) {
  3288. RoleBits = 0;
  3289. } else {
  3290. printf( "Invalid Role: %s\n\n", Role );
  3291. CommandUsage(BROWSER_DEBUG_SET_EMULATEDDOMAIN);
  3292. return;
  3293. }
  3294. NetStatus = I_BrowserSetNetlogonState(
  3295. NULL,
  3296. EmulatedDomainName,
  3297. EmulatedComputerName,
  3298. RoleBits );
  3299. if ( NetStatus != NERR_Success ) {
  3300. printf( "Can't set domain role: %s\n", get_error_text(NetStatus));
  3301. }
  3302. }
  3303. NET_API_STATUS
  3304. RenameDomain(
  3305. IN PCHAR OldDomain,
  3306. IN PCHAR NewDomain,
  3307. IN BOOL ValidateOnly
  3308. )
  3309. /*++
  3310. Routine Description:
  3311. This function rename the primary domain or emulated domain.
  3312. Arguments:
  3313. OldDomain - existing name of the domain
  3314. NewDomain - new name of the domain
  3315. Return Value:
  3316. Status - The status of the operation.
  3317. --*/
  3318. {
  3319. NET_API_STATUS Status;
  3320. HANDLE BrowserHandle;
  3321. LPBYTE Where;
  3322. UCHAR PacketBuffer[sizeof(LMDR_REQUEST_PACKET)+(DNLEN+1)*sizeof(WCHAR)];
  3323. PLMDR_REQUEST_PACKET RequestPacket = (PLMDR_REQUEST_PACKET)PacketBuffer;
  3324. WCHAR NewUnicodeDomainName[DNLEN+1];
  3325. WCHAR OldUnicodeDomainName[DNLEN+1];
  3326. //
  3327. // Convert the names to unicode
  3328. //
  3329. if ( OldDomain == NULL ) {
  3330. *OldUnicodeDomainName = L'\0';
  3331. } else {
  3332. NetpCopyStrToWStr( OldUnicodeDomainName, OldDomain );
  3333. }
  3334. if ( NewDomain == NULL ) {
  3335. *NewUnicodeDomainName = L'\0';
  3336. } else {
  3337. NetpCopyStrToWStr( NewUnicodeDomainName, NewDomain );
  3338. }
  3339. //
  3340. // Open the browser driver.
  3341. Status = OpenBrowser(&BrowserHandle);
  3342. if (Status != NERR_Success) {
  3343. return(Status);
  3344. }
  3345. //
  3346. // Build the request to pass to the browser.
  3347. //
  3348. RequestPacket->Version = LMDR_REQUEST_PACKET_VERSION_DOM;
  3349. RequestPacket->Parameters.DomainRename.ValidateOnly = ValidateOnly;
  3350. RtlInitUnicodeString( &RequestPacket->TransportName, NULL );
  3351. RtlInitUnicodeString( &RequestPacket->EmulatedDomainName, OldUnicodeDomainName );
  3352. RequestPacket->Parameters.DomainRename.DomainNameLength = wcslen( NewUnicodeDomainName ) * sizeof(WCHAR);
  3353. wcscpy( RequestPacket->Parameters.DomainRename.DomainName,
  3354. NewUnicodeDomainName );
  3355. //
  3356. // This is a simple IoControl - It just sends down the packet.
  3357. //
  3358. Status = BrDgReceiverIoControl(
  3359. BrowserHandle,
  3360. IOCTL_LMDR_RENAME_DOMAIN,
  3361. RequestPacket,
  3362. FIELD_OFFSET(LMDR_REQUEST_PACKET, Parameters.DomainRename.DomainName) +
  3363. RequestPacket->Parameters.DomainRename.DomainNameLength,
  3364. NULL,
  3365. 0,
  3366. NULL);
  3367. if (Status != NERR_Success) {
  3368. printf("Unable rename domain from %s to %s : %s\n",
  3369. OldDomain,
  3370. NewDomain,
  3371. get_error_text(Status));
  3372. exit(Status);
  3373. }
  3374. return Status;
  3375. }
  3376. VOID
  3377. _cdecl
  3378. main (argc, argv)
  3379. int argc;
  3380. char *argv[];
  3381. {
  3382. NET_API_STATUS Status;
  3383. ULONG ControlCode;
  3384. ULONG Options = 0;
  3385. LPTSTR Server = NULL;
  3386. TCHAR ServerBuffer[CNLEN+1];
  3387. ULONG i = 0;
  3388. DWORD status;
  3389. strcpy(ProgramName,argv[0]) ; // cannot overflow, since buffer > MAXPATH
  3390. _strupr(ProgramName) ;
  3391. if (argc < 2) {
  3392. usage(NULL);
  3393. exit(1);
  3394. }
  3395. //
  3396. // Look up the command in the list of commands.
  3397. //
  3398. while (CommandSwitchList[i].SwitchName != NULL) {
  3399. if (!_stricmp(argv[1], CommandSwitchList[i].SwitchName) ||
  3400. !_stricmp(argv[1], CommandSwitchList[i].ShortName)) {
  3401. ControlCode = CommandSwitchList[i].SwitchValue;
  3402. break;
  3403. }
  3404. i += 1;
  3405. }
  3406. if (CommandSwitchList[i].SwitchName == NULL) {
  3407. usage("Unknown switch specified");
  3408. exit(5);
  3409. }
  3410. //
  3411. // If an incorrect number of arguments were supplied,
  3412. // complain.
  3413. //
  3414. if ( look_for_help(argc, argv) ||
  3415. argc < CommandSwitchList[i].MinArgc ||
  3416. argc > CommandSwitchList[i].MaxArgc ) {
  3417. CommandUsage( ControlCode );
  3418. exit(4);
  3419. }
  3420. //
  3421. // Do command specific processing.
  3422. //
  3423. switch (ControlCode) {
  3424. case BROWSER_DEBUG_SET_DEBUG:
  3425. {
  3426. ULONG i = 0;
  3427. if ((Options = atol(argv[2])) == 0) {
  3428. PCHAR SwitchText;
  3429. if (argv[2][0] == '+') {
  3430. SwitchText = &argv[2][1];
  3431. ControlCode = BROWSER_DEBUG_SET_DEBUG;
  3432. } else if (argv[2][0] == '-') {
  3433. SwitchText = &argv[2][1];
  3434. ControlCode = BROWSER_DEBUG_CLEAR_DEBUG;
  3435. } else {
  3436. CommandUsage( ControlCode );
  3437. exit(4);
  3438. }
  3439. while (DebugSwitchList[i].SwitchName != NULL) {
  3440. if (!_stricmp(SwitchText, DebugSwitchList[i].SwitchName)) {
  3441. Options = DebugSwitchList[i].SwitchValue;
  3442. break;
  3443. }
  3444. i += 1;
  3445. }
  3446. if (DebugSwitchList[i].SwitchName == NULL) {
  3447. CommandUsage( ControlCode );
  3448. exit(4);
  3449. }
  3450. if (argc == 4) {
  3451. status = MultiByteToWideChar(
  3452. CP_ACP,
  3453. 0,
  3454. argv[3],
  3455. strlen(argv[3])+1,
  3456. ServerBuffer,
  3457. CNLEN
  3458. );
  3459. if ( ERROR_SUCCESS != status ) {
  3460. CommandUsage( ControlCode );
  3461. exit(4);
  3462. }
  3463. Server = ServerBuffer;
  3464. }
  3465. }
  3466. }
  3467. break;
  3468. case BROWSER_DEBUG_DUMP_NETWORKS:
  3469. DumpTransportList();
  3470. exit(0);
  3471. break;
  3472. case BROWSER_DEBUG_BREAK_POINT:
  3473. case BROWSER_DEBUG_TRUNCATE_LOG:
  3474. break;
  3475. case BROWSER_DEBUG_ENABLE_BROWSER:
  3476. {
  3477. NET_API_STATUS Status;
  3478. Status = EnableService(TEXT("BROWSER"));
  3479. if (Status != NERR_Success) {
  3480. printf("Unable to enable browser service - %ld\n", Status);
  3481. }
  3482. exit(Status);
  3483. }
  3484. break;
  3485. case BROWSER_DEBUG_BOWSERDEBUG:
  3486. if (argc == 3) {
  3487. if (_stricmp(argv[2], "TRUNCATE") == 0) {
  3488. TruncateBowserLog();
  3489. } else if (_stricmp(argv[2], "CLOSE") == 0) {
  3490. CloseBowserLog();
  3491. } else {
  3492. CommandUsage( BROWSER_DEBUG_BOWSERDEBUG );
  3493. }
  3494. } else if (argc == 4) {
  3495. if (_stricmp(argv[2], "OPEN") == 0) {
  3496. OpenBowserLog(argv[3]);
  3497. } else if (_stricmp(argv[2], "DEBUG") == 0) {
  3498. SetBowserDebug(argv[3]);
  3499. } else {
  3500. CommandUsage( BROWSER_DEBUG_BOWSERDEBUG );
  3501. }
  3502. }
  3503. exit(0);
  3504. case BROWSER_DEBUG_ELECT:
  3505. Elect(argv[2], argv[3], (argc == 5) ? argv[4] : NULL );
  3506. exit(0);
  3507. break;
  3508. case BROWSER_DEBUG_GET_MASTER:
  3509. GetMaster(argv[2], argv[3]);
  3510. exit(0);
  3511. break;
  3512. case BROWSER_DEBUG_TICKLE:
  3513. Tickle(argv[2], argv[3], (argc == 5) ? argv[4] : NULL );
  3514. exit(0);
  3515. break;
  3516. case BROWSER_DEBUG_FORCE_ANNOUNCE:
  3517. ForceAnnounce(argv[2], argv[3], (argc == 5) ? argv[4] : NULL );
  3518. exit(0);
  3519. break;
  3520. case BROWSER_DEBUG_GETPDC:
  3521. GetPdc(argv[2], argv[3]);
  3522. exit(0);
  3523. break;
  3524. case BROWSER_DEBUG_ADD_MASTERNAME:
  3525. AddMasterName(argv[2], argv[3], (argc==5 ? TRUE : FALSE));
  3526. exit(0);
  3527. break;
  3528. case BROWSER_DEBUG_ADD_DOMAINNAME:
  3529. AddDomainName(argv[2], argv[3], (argc==5 ? TRUE : FALSE));
  3530. exit(0);
  3531. break;
  3532. case BROWSER_DEBUG_FIND_MASTER:
  3533. FindMaster(argv[2], (argc==3 ? NULL : argv[3]) );
  3534. exit(0);
  3535. break;
  3536. case BROWSER_DEBUG_GET_BACKUP_LIST:
  3537. GetBlist(argv[2], (argc == 3 ? NULL : argv[3]), (BOOLEAN)(argc==5? TRUE : FALSE));
  3538. exit(0);
  3539. break;
  3540. case BROWSER_DEBUG_ANNOUNCE_MASTER:
  3541. AnnounceMaster(argv[2], argv[3], (argc == 5) ? argv[4] : NULL );
  3542. exit(0);
  3543. break;
  3544. case BROWSER_DEBUG_ILLEGAL_DGRAM:
  3545. IllegalDatagram(argv[2], argv[3], (argc == 5) ? argv[4] : NULL );
  3546. exit(0);
  3547. break;
  3548. case BROWSER_DEBUG_GET_OTHLIST:
  3549. GetOtherdomains(argv[2]);
  3550. exit(0);
  3551. break;
  3552. case BROWSER_DEBUG_VIEW:
  3553. View(argv[2],
  3554. (argc >= 4 ? argv[3] : NULL),
  3555. (argc >= 5 ? argv[4] : NULL),
  3556. (argc >= 6 ? argv[5] : NULL),
  3557. #ifndef _PSS_RELEASE
  3558. (argc == 7 ? TRUE : FALSE));
  3559. #else
  3560. FALSE);
  3561. #endif
  3562. exit(0);
  3563. break;
  3564. case BROWSER_DEBUG_LIST_WFW:
  3565. ListWFW(argv[2]) ;
  3566. exit(0);
  3567. break;
  3568. case BROWSER_DEBUG_RPCLIST:
  3569. RpcList(argv[2], (argc >= 4 ? argv[3] : NULL), (argc >= 5 ? argv[4] : NULL), (argc == 6 ? TRUE : FALSE));
  3570. exit(0);
  3571. break;
  3572. case BROWSER_DEBUG_RPCCMP:
  3573. RpcCmp(argv[2], (argc >= 4 ? argv[3] : NULL), (argc >= 5 ? argv[4] : NULL), (argc == 6 ? TRUE : FALSE));
  3574. exit(0);
  3575. break;
  3576. case BROWSER_DEBUG_LOCAL_BRLIST:
  3577. GetLocalList(argv[2], (argc >= 4 ? argv[3] : NULL), (argc >= 5 ? argv[4] : NULL) );
  3578. exit(0);
  3579. break;
  3580. case BROWSER_DEBUG_GET_NETBIOSNAMES:
  3581. PrintNetbiosNames(argv[2], (argc >= 4 ? argv[3] : NULL));
  3582. exit(0);
  3583. break;
  3584. case BROWSER_DEBUG_ADD_ALTERNATE:
  3585. AddAlternateComputerName(argv[2], argv[3], (argc >= 5 ? argv[4] : NULL));
  3586. exit(0);
  3587. break;
  3588. case BROWSER_DEBUG_BIND_TRANSPORT:
  3589. BindTransport( TRUE, argv[2], (argc >= 4 ? argv[3] : NULL), (argc >= 5 ? argv[4] : NULL) );
  3590. exit(0);
  3591. break;
  3592. case BROWSER_DEBUG_UNBIND_TRANSPORT:
  3593. BindTransport( FALSE, argv[2], (argc >= 4 ? argv[3] : NULL), (argc >= 5 ? argv[4] : NULL) );
  3594. exit(0);
  3595. break;
  3596. case BROWSER_DEBUG_STATISTICS:
  3597. DumpStatistics(argc, argv[2]);
  3598. exit(0);
  3599. break;
  3600. case BROWSER_DEBUG_ANNOUNCE:
  3601. Announce(argv[2], argv[3], (argc >= 5 ? argv[4] : NULL ), (argc >= 6 ? TRUE : FALSE));
  3602. exit(0);
  3603. break;
  3604. case BROWSER_DEBUG_POPULATE_DOMAIN:
  3605. case BROWSER_DEBUG_POPULATE_SERVER:
  3606. Populate((ControlCode == BROWSER_DEBUG_POPULATE_DOMAIN ? TRUE : FALSE),
  3607. argv[2],
  3608. argv[3],
  3609. (argc >= 6 ? argv[5] : NULL),
  3610. argv[4],
  3611. (argc >= 7 ? argv[6] : NULL));
  3612. exit(0);
  3613. break;
  3614. case BROWSER_DEBUG_GET_WINSSERVER:
  3615. GetWinsServer(argv[2]);
  3616. exit(0);
  3617. break;
  3618. case BROWSER_DEBUG_GET_DOMAINLIST:
  3619. GetDomainList(argv[2]);
  3620. exit(0);
  3621. break;
  3622. case BROWSER_DEBUG_STATUS:
  3623. {
  3624. PCHAR Domain;
  3625. BOOL Verbose = FALSE;
  3626. if (argc == 4) {
  3627. if (_stricmp(argv[2], "-v") == 0) {
  3628. Verbose = TRUE;
  3629. Domain = argv[3];
  3630. } else {
  3631. CommandUsage( ControlCode );
  3632. exit(4);
  3633. }
  3634. } else if (argc == 3) {
  3635. if (_stricmp(argv[2], "-v") == 0) {
  3636. Verbose = TRUE;
  3637. Domain = NULL;
  3638. } else {
  3639. Domain = argv[2];
  3640. }
  3641. } else {
  3642. Domain = NULL;
  3643. }
  3644. BrowserStatus(Verbose, Domain);
  3645. }
  3646. exit(0);
  3647. break;
  3648. case BROWSER_DEBUG_RENAME_DOMAIN:
  3649. RenameDomain(argv[2], argv[3], (argc >= 5));
  3650. exit(0);
  3651. break;
  3652. case BROWSER_DEBUG_SET_EMULATEDDOMAIN:
  3653. SetEmulatedDomain(argv[2], argv[3], (argc >= 5 ? argv[4] : NULL) );
  3654. exit(0);
  3655. break;
  3656. case BROWSER_DEBUG_SET_EMULATEDDOMAINENUM:
  3657. EnumEmulatedDomains();
  3658. exit(0);
  3659. break;
  3660. }
  3661. Status = I_BrowserDebugCall(Server, ControlCode, Options);
  3662. printf("Api call returned %ld\n", Status);
  3663. }