Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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