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.

1149 lines
34 KiB

  1. //++
  2. //
  3. // Copyright (C) Microsoft Corporation, 1987 - 1999
  4. //
  5. // Module Name:
  6. //
  7. // nettest.c
  8. //
  9. // Abstract:
  10. //
  11. // Test to ensure that a workstation has network (IP) connectivity to
  12. // the outside.
  13. //
  14. // Author:
  15. //
  16. // 15-Dec-1997 (cliffv)
  17. // Anilth - 4-20-1998
  18. //
  19. // Environment:
  20. //
  21. // User mode only.
  22. // Contains NT-specific code.
  23. //
  24. // Revision History:
  25. //
  26. // 1-June-1998 (denisemi) add DnsServerHasDCRecords to check DC dns records
  27. // registration
  28. //
  29. // 26-June-1998 (t-rajkup) add general tcp/ip , dhcp and routing,
  30. // winsock, ipx, wins and netbt information.
  31. //--
  32. //
  33. // Common include files.
  34. //
  35. #include "precomp.h"
  36. #include "ipxtest.h"
  37. #include "ipcfgtest.h"
  38. #include "machine.h"
  39. #include "global.h"
  40. #include "crtdbg.h"
  41. #include <locale.h>
  42. //////////////////////////////////////////////////////////////////////////////
  43. //
  44. // Globals
  45. //
  46. //////////////////////////////////////////////////////////////////////////////
  47. const TCHAR c_szLogFileName[] = _T("NetDiag.log");
  48. //BOOL IpConfigCalled = FALSE;
  49. //BOOL ProblemBased = FALSE;
  50. int ProblemNumber;
  51. //
  52. // New functions for displaying routing table - Rajkumar
  53. //
  54. #define WILD_CARD (ULONG)(-1)
  55. #define ROUTE_DATA_STRING_SIZE 300
  56. #define MAX_METRIC 9999
  57. #define ROUTE_SEPARATOR ','
  58. int match( const char * p, const char * s );
  59. // Replaced by pResults->IpConfig.pFixedInfo
  60. //PFIXED_INFO GlobalIpconfigFixedInfo = NULL;
  61. // Replaced by per-adapter info, pResults->pArrayInterface[i].IpConfig
  62. //PADAPTER_INFO GlobalIpconfigAdapterInfo = NULL;
  63. // Replaced by per-adapter info, pResults->pArrayInterface[i].IpConfig.pAdapterInfo
  64. //PIP_ADAPTER_INFO IpGlobalIpconfigAdapterInfo = NULL;
  65. // See pResults->IpConfig.fDhcpEnabled
  66. //BOOLEAN GlobalDhcpEnabled;
  67. // See pResults->NetBt.Transports
  68. //LIST_ENTRY GlobalNetbtTransports;
  69. // See pResults->NetBt.cTransportCount
  70. //ULONG GlobalNetbtTransportCount;
  71. // !!! not replaced yet
  72. // See pResults->Global.listTestedDomains
  73. //LIST_ENTRY GlobalTestedDomains;
  74. //
  75. // Globals defining the command line arguments.
  76. //
  77. // Replaced by pParams->fVerbose
  78. //BOOL Verbose;
  79. // Replaced by pParams->fReallyVerbose
  80. // Maintain this global variable so that we don't mess up the compiling
  81. // of getdcnam.c
  82. BOOL ReallyVerbose;
  83. // Replaced by pParams->fDebugVerbose
  84. //BOOL DebugVerbose;
  85. // Replaced by pParams->fFixProblems
  86. //BOOL GlobalFixProblems;
  87. // Replaced by pParams->fDcAccountEnum
  88. //BOOL GlobalDcAccountEnum;
  89. // !!! not replaced yet
  90. //PTESTED_DOMAIN GlobalQueriedDomain;
  91. //
  92. // Describe the domain this machine is a member of
  93. //
  94. // Replaced by pResults->Global.pszCurrentBuildNumber
  95. //int GlobalNtBuildNumber;
  96. // Replaced by pResults->Global.pPrimaryDomainInfo
  97. //PDSROLE_PRIMARY_DOMAIN_INFO_BASIC GlobalDomainInfo = NULL;
  98. // Replaced by pResults->Global.pMemberDomain
  99. //PTESTED_DOMAIN GlobalMemberDomain;
  100. //
  101. // Who we're currently logged on as
  102. //
  103. // Replaced by pResults->Global.pLogonUser
  104. //PUNICODE_STRING GlobalLogonUser;
  105. // Replaced by pResults->Global.pLogonDomainName
  106. //PUNICODE_STRING GlobalLogonDomainName;
  107. // Replaced by pResults->Global.pLogonDomain
  108. //PTESTED_DOMAIN GlobalLogonDomain;
  109. // Replaced by pResults->Global.fLogonWithCachedCredentials
  110. //BOOLEAN GlobalLogonWithCachedCredentials = FALSE;
  111. //
  112. // A Zero GUID for comparison
  113. //
  114. GUID NlDcZeroGuid;
  115. //
  116. // State determined by previous tests
  117. //
  118. // Replaced by pResults->Global.fNetlogonIsRunning
  119. //BOOL GlobalNetlogonIsRunning = FALSE; // Netlogon is running on this machine
  120. // !!! not replaced yet
  121. // Replaced by pResults->Global.fKerberosIsWorking
  122. //BOOL GlobalKerberosIsWorking = FALSE; // Kerberos is working
  123. //
  124. // Netbios name of this machine
  125. //
  126. // Replaced by pResults->Global.swzNetBiosName
  127. //WCHAR GlobalNetbiosComputerName[MAX_COMPUTERNAME_LENGTH+1];
  128. // Replaced by pResults->Global.szDnsHostName
  129. //CHAR GlobalDnsHostName[DNS_MAX_NAME_LENGTH+1];
  130. // Replaced by pResults->Global.pszDnsDomainName
  131. //LPSTR GlobalDnsDomainName;
  132. //(nsun) this macro already exists in <objbase.h>
  133. //
  134. // Macro for comparing GUIDs
  135. //
  136. /*
  137. #define InlineIsEqualGUID(rguid1, rguid2) \
  138. (((PLONG) rguid1)[0] == ((PLONG) rguid2)[0] && \
  139. ((PLONG) rguid1)[1] == ((PLONG) rguid2)[1] && \
  140. ((PLONG) rguid1)[2] == ((PLONG) rguid2)[2] && \
  141. ((PLONG) rguid1)[3] == ((PLONG) rguid2)[3])
  142. #define IsEqualGUID(rguid1, rguid2) InlineIsEqualGUID(rguid1, rguid2)
  143. */
  144. DSGETDCNAMEW NettestDsGetDcNameW;
  145. PFNGUIDTOFRIENDLYNAME pfnGuidToFriendlyName = NULL;
  146. /*---------------------------------------------------------------------------
  147. Function prototypes
  148. ---------------------------------------------------------------------------*/
  149. HRESULT LoadNamesForListOfTests();
  150. void FreeNamesForListOfTests();
  151. void DoGlobalPrint(NETDIAG_PARAMS *pParams, NETDIAG_RESULT *pResults);
  152. void DoPerInterfacePrint(NETDIAG_PARAMS *pParams, NETDIAG_RESULT *pResults);
  153. /*---------------------------------------------------------------------------
  154. Functions provided by ipconfig
  155. ---------------------------------------------------------------------------*/
  156. #define DECLARE_TEST_FUNCTIONS(_test) \
  157. HRESULT _test##Test(NETDIAG_PARAMS *, NETDIAG_RESULT *); \
  158. void _test##GlobalPrint(NETDIAG_PARAMS *, NETDIAG_RESULT *); \
  159. void _test##PerInterfacePrint(NETDIAG_PARAMS *, NETDIAG_RESULT *, INTERFACE_RESULT *); \
  160. void _test##Cleanup(NETDIAG_PARAMS *, NETDIAG_RESULT *);
  161. DECLARE_TEST_FUNCTIONS(IpConfig);
  162. DECLARE_TEST_FUNCTIONS(Member);
  163. DECLARE_TEST_FUNCTIONS(IpLoopBk);
  164. DECLARE_TEST_FUNCTIONS(NetBT);
  165. DECLARE_TEST_FUNCTIONS(Autonet);
  166. DECLARE_TEST_FUNCTIONS(DefGw);
  167. DECLARE_TEST_FUNCTIONS(NbtNm);
  168. DECLARE_TEST_FUNCTIONS(Wins);
  169. DECLARE_TEST_FUNCTIONS(Bindings);
  170. DECLARE_TEST_FUNCTIONS(Dns);
  171. DECLARE_TEST_FUNCTIONS(Browser);
  172. DECLARE_TEST_FUNCTIONS(Winsock);
  173. DECLARE_TEST_FUNCTIONS(Route);
  174. DECLARE_TEST_FUNCTIONS(Netstat);
  175. DECLARE_TEST_FUNCTIONS(Ndis);
  176. DECLARE_TEST_FUNCTIONS(WAN);
  177. #ifndef _WIN64
  178. //Netware and IPX support is removed from WIN64
  179. DECLARE_TEST_FUNCTIONS(Netware);
  180. DECLARE_TEST_FUNCTIONS(Ipx);
  181. #endif
  182. DECLARE_TEST_FUNCTIONS(Trust);
  183. DECLARE_TEST_FUNCTIONS(Modem);
  184. DECLARE_TEST_FUNCTIONS(Kerberos);
  185. DECLARE_TEST_FUNCTIONS(DcList);
  186. DECLARE_TEST_FUNCTIONS(LDAP);
  187. DECLARE_TEST_FUNCTIONS(DsGetDc);
  188. DECLARE_TEST_FUNCTIONS(IPSec);
  189. //////////////////////////////////////////////////////////////////////////////
  190. //
  191. // List of tests to run
  192. //
  193. //////////////////////////////////////////////////////////////////////////////
  194. typedef struct
  195. {
  196. // Each of these strings has a max of 256 characters
  197. UINT uIdsShortName; // ID of the string for the short name
  198. UINT uIdsLongName; // ID of the string for the long name
  199. HRESULT (*TestProc)(NETDIAG_PARAMS* pParams, NETDIAG_RESULT* pResults);
  200. void (*SystemPrintProc)(NETDIAG_PARAMS *pParams, NETDIAG_RESULT *pRes);
  201. void (*GlobalPrintProc)(NETDIAG_PARAMS *pParams, NETDIAG_RESULT *pRes);
  202. void (*PerInterfacePrintProc)(NETDIAG_PARAMS *pParams,
  203. NETDIAG_RESULT *pRes,
  204. INTERFACE_RESULT *pIfRes);
  205. void (*CleanupProc)(NETDIAG_PARAMS *pParams, NETDIAG_RESULT *pResults);
  206. BOOL fSkippable;
  207. BOOL fPerDomainTest;
  208. BOOL fSkipped;
  209. BOOL fPerformed;
  210. // We will call LoadString() on the id's above to get these
  211. // strings.
  212. LPTSTR pszShortName;
  213. LPTSTR pszLongName;
  214. } TEST_INFO;
  215. #define EACH_TEST(_szID, _uShortIDS, _uLongIDS, _skip, _perdomain) \
  216. { _uShortIDS, _uLongIDS, _szID##Test, NULL, _szID##GlobalPrint, \
  217. _szID##PerInterfacePrint, _szID##Cleanup, _skip, _perdomain, \
  218. FALSE, FALSE, NULL, NULL}
  219. #define SYSTEM_PRINT_TEST(_szID, _uShortIDS, _uLongIDS, _skip, _perdomain) \
  220. { _uShortIDS, _uLongIDS, _szID##Test, _szID##GlobalPrint, NULL, \
  221. _szID##PerInterfacePrint, _szID##Cleanup, _skip, _perdomain, \
  222. FALSE, FALSE, NULL, NULL}
  223. //
  224. // Tests below are marked "skippable" unless subsequent tests will AV if the
  225. // test isn't run.
  226. //
  227. static TEST_INFO s_rgListOfTests[] =
  228. {
  229. // IP Configuration
  230. SYSTEM_PRINT_TEST( Ndis, IDS_NDIS_SHORT, IDS_NDIS_LONG, FALSE, FALSE),
  231. EACH_TEST( IpConfig,IDS_IPCONFIG_SHORT, IDS_IPCONFIG_LONG, TRUE, FALSE),
  232. EACH_TEST( Member, IDS_MEMBER_SHORT, IDS_MEMBER_LONG, FALSE,FALSE),
  233. EACH_TEST( NetBT, IDS_NETBT_SHORT, IDS_NETBT_LONG, FALSE,FALSE),
  234. EACH_TEST( Autonet, IDS_AUTONET_SHORT, IDS_AUTONET_LONG, TRUE, FALSE),
  235. EACH_TEST( IpLoopBk,IDS_IPLOOPBK_SHORT, IDS_IPLOOPBK_LONG, TRUE, FALSE),
  236. EACH_TEST( DefGw, IDS_DEFGW_SHORT, IDS_DEFGW_LONG, TRUE, FALSE),
  237. EACH_TEST( NbtNm, IDS_NBTNM_SHORT, IDS_NBTNM_LONG, TRUE, FALSE),
  238. EACH_TEST( Wins, IDS_WINS_SHORT, IDS_WINS_LONG, TRUE, FALSE),
  239. EACH_TEST( Winsock, IDS_WINSOCK_SHORT, IDS_WINSOCK_LONG, TRUE, FALSE),
  240. EACH_TEST( Dns, IDS_DNS_SHORT, IDS_DNS_LONG, TRUE, FALSE),
  241. EACH_TEST( Browser, IDS_BROWSER_SHORT, IDS_BROWSER_LONG, TRUE, FALSE),
  242. EACH_TEST( DsGetDc, IDS_DSGETDC_SHORT, IDS_DSGETDC_LONG, TRUE, TRUE ),
  243. EACH_TEST( DcList, IDS_DCLIST_SHORT, IDS_DCLIST_LONG, TRUE, TRUE ),
  244. EACH_TEST( Trust, IDS_TRUST_SHORT, IDS_TRUST_LONG, TRUE, FALSE),
  245. EACH_TEST( Kerberos,IDS_KERBEROS_SHORT, IDS_KERBEROS_LONG, TRUE, FALSE ),
  246. EACH_TEST( LDAP, IDS_LDAP_SHORT, IDS_LDAP_LONG, TRUE, TRUE ),
  247. EACH_TEST( Route, IDS_ROUTE_SHORT, IDS_ROUTE_LONG, TRUE, FALSE ),
  248. EACH_TEST( Netstat, IDS_NETSTAT_SHORT, IDS_NETSTAT_LONG, TRUE, FALSE),
  249. EACH_TEST( Bindings,IDS_BINDINGS_SHORT, IDS_BINDINGS_LONG, TRUE, FALSE),
  250. EACH_TEST( WAN, IDS_WAN_SHORT, IDS_WAN_LONG, TRUE, FALSE),
  251. EACH_TEST( Modem, IDS_MODEM_SHORT, IDS_MODEM_LONG, TRUE, FALSE),
  252. #ifndef _WIN64
  253. //Netware and IPX support is removed from WIN64
  254. EACH_TEST( Netware, IDS_NETWARE_SHORT, IDS_NETWARE_LONG, TRUE, FALSE),
  255. EACH_TEST( Ipx, IDS_IPX_SHORT, IDS_IPX_LONG, TRUE, FALSE),
  256. #endif
  257. EACH_TEST( IPSec, IDS_IPSEC_SHORT, IDS_IPSEC_LONG, TRUE, FALSE)
  258. };
  259. /////////////////////////////////////////////////////////////////////////////
  260. //
  261. // List of problems and the corresponding tests to run
  262. //
  263. /////////////////////////////////////////////////////////////////////////////
  264. // max no of tests
  265. #define NO_OF_TESTS 25
  266. typedef BOOL (*FuncPtr)(NETDIAG_PARAMS* pParams, NETDIAG_RESULT* pResults);
  267. typedef struct _A_PROBLEM {
  268. LPTSTR problem; // Problem description
  269. LONG n; // no of tests
  270. FuncPtr TestProc[NO_OF_TESTS];
  271. } A_PROBLEM;
  272. // Number of problems defined
  273. #define NO_OF_PROBLEMS 2
  274. A_PROBLEM ListOfProblems[] = {
  275. _T("Fake test"), 1 , IpConfigTest, NULL, NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
  276. // "Not Able to Reach Other Segments Of the Network", 1 , DefGwTest, NULL, NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
  277. // "Not Able to Resolve NetBios Names", 1 , WINSTest, NULL, NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
  278. };
  279. /*!--------------------------------------------------------------------------
  280. ParseArgs
  281. Routine Description:
  282. Parse the command line arguments
  283. Arguments:
  284. argc - the number of command-line arguments.
  285. argv - an array of pointers to the arguments.
  286. pParams - this function sets these values
  287. pResults - additional output
  288. Return Value:
  289. 0: All OK
  290. Exit status
  291. Author: KennT
  292. ---------------------------------------------------------------------------*/
  293. int
  294. ParseArgs(
  295. IN int argc,
  296. IN TCHAR ** argv,
  297. IN OUT NETDIAG_PARAMS *pParams,
  298. IN OUT NETDIAG_RESULT *pResults
  299. )
  300. {
  301. LPSTR pszArgument;
  302. LPSTR TestName;
  303. int ArgumentIndex;
  304. ULONG i;
  305. BOOL SeenTestOption = FALSE;
  306. PTESTED_DOMAIN pQueriedDomain;
  307. //
  308. // Flags used by problem option
  309. //
  310. BOOL OtherOptions = FALSE;
  311. //
  312. // Set the defaults
  313. //
  314. pParams->fVerbose = TRUE;
  315. pParams->fReallyVerbose = FALSE;
  316. pParams->fDebugVerbose = FALSE;
  317. pParams->fFixProblems = FALSE;
  318. pParams->fDcAccountEnum = FALSE;
  319. pParams->fProblemBased = FALSE;
  320. pParams->nProblemNumber = 0;
  321. //
  322. // Loop through the arguments handle each in turn
  323. //
  324. for ( ArgumentIndex=1; ArgumentIndex<argc; ArgumentIndex++ ) {
  325. pszArgument = argv[ArgumentIndex];
  326. if ( StriCmp( pszArgument, _T("/q") ) == 0 ||
  327. StriCmp( pszArgument, _T("-q") ) == 0 )
  328. {
  329. if ( pParams->fReallyVerbose || pParams->fProblemBased )
  330. {
  331. goto Usage;
  332. }
  333. pParams->fVerbose = FALSE;
  334. OtherOptions = TRUE;
  335. }
  336. else if ( StriCmp( pszArgument, _T("/v") ) == 0 ||
  337. StriCmp( pszArgument, _T("-v") ) == 0 )
  338. {
  339. if ( !pParams->fVerbose || pParams->fProblemBased)
  340. {
  341. goto Usage;
  342. }
  343. pParams->fVerbose = TRUE;
  344. pParams->fReallyVerbose = TRUE;
  345. OtherOptions = TRUE;
  346. }
  347. else if ( StriCmp( pszArgument, _T("/debug") ) == 0 ||
  348. StriCmp( pszArgument, _T("-debug") ) == 0 )
  349. {
  350. if ( !pParams->fVerbose || pParams->fProblemBased)
  351. {
  352. goto Usage;
  353. }
  354. pParams->fVerbose = TRUE;
  355. pParams->fReallyVerbose = TRUE;
  356. pParams->fDebugVerbose = TRUE;
  357. OtherOptions = TRUE;
  358. }
  359. else if ( StriCmp( pszArgument, _T("/fix") ) == 0 ||
  360. StriCmp( pszArgument, _T("-fix") ) == 0 )
  361. {
  362. if (pParams->fProblemBased)
  363. goto Usage;
  364. pParams->fFixProblems = TRUE;
  365. OtherOptions = TRUE;
  366. }
  367. else if ( StriCmp( pszArgument, _T("/DcAccountEnum") ) == 0 ||
  368. StriCmp( pszArgument, _T("-DcAccountEnum") ) == 0 )
  369. {
  370. if (pParams->fProblemBased)
  371. goto Usage;
  372. pParams->fDcAccountEnum = TRUE;
  373. OtherOptions = TRUE;
  374. //
  375. // Allow the caller to specify the name of a domain to query.
  376. //
  377. }
  378. else if ( StrniCmp( pszArgument, _T("/d:"), 3 ) == 0 ||
  379. StrniCmp( pszArgument, _T("-d:"), 3 ) == 0 )
  380. {
  381. WCHAR UnicodeDomainName[MAX_PATH+1];
  382. if (pParams->fProblemBased)
  383. goto Usage;
  384. OtherOptions = TRUE;
  385. NetpCopyStrToWStr( UnicodeDomainName, &pszArgument[3] );
  386. pQueriedDomain = AddTestedDomain(pParams, pResults,
  387. UnicodeDomainName, NULL, FALSE );
  388. if ( pQueriedDomain == NULL )
  389. {
  390. goto Usage;
  391. }
  392. //
  393. // Allow the caller to skip certain tests
  394. //
  395. }
  396. else if ( StrniCmp( pszArgument, _T("/skip:"), 6 ) == 0 ||
  397. StrniCmp( pszArgument, _T("-skip:"), 6 ) == 0 )
  398. {
  399. TestName = &pszArgument[6];
  400. OtherOptions = TRUE;
  401. if (pParams->fProblemBased)
  402. goto Usage;
  403. for ( i=0; i < DimensionOf(s_rgListOfTests); i++)
  404. {
  405. if ( StriCmp( s_rgListOfTests[i].pszShortName, TestName ) == 0 )
  406. {
  407. //
  408. // If the caller specified a non-optional test,
  409. // tell him.
  410. //
  411. if ( !s_rgListOfTests[i].fSkippable )
  412. {
  413. //IDS_GLOBAL_NOT_OPTIONAL "'%s' is not an optional test.\n"
  414. PrintMessage(pParams, IDS_GLOBAL_NOT_OPTIONAL, TestName );
  415. goto Usage;
  416. }
  417. s_rgListOfTests[i].fSkipped = TRUE;
  418. break;
  419. }
  420. }
  421. if ( i >= DimensionOf(s_rgListOfTests) )
  422. {
  423. //IDS_GLOBAL_NOT_VALID_TEST "'%s' is not an valid test name.\n"
  424. PrintMessage( pParams, IDS_GLOBAL_NOT_VALID_TEST, TestName );
  425. goto Usage;
  426. }
  427. //
  428. // Handle all other parameters
  429. //
  430. }
  431. else if ( StrniCmp( pszArgument, _T("/test:"),6 ) == 0 ||
  432. StrniCmp( pszArgument, _T("-test:"),6 ) == 0 )
  433. {
  434. TestName = &pszArgument[6];
  435. OtherOptions = TRUE;
  436. if (pParams->fProblemBased)
  437. goto Usage;
  438. for ( i =0; i < DimensionOf(s_rgListOfTests); i++)
  439. {
  440. if ( StriCmp( s_rgListOfTests[i].pszShortName, TestName ) == 0)
  441. s_rgListOfTests[i].fSkipped = FALSE;
  442. else {
  443. if (!SeenTestOption && s_rgListOfTests[i].fSkippable)
  444. s_rgListOfTests[i].fSkipped = TRUE;
  445. }
  446. }
  447. SeenTestOption = TRUE;
  448. }
  449. else if( StrniCmp( pszArgument, _T("/l"), 5) == 0 ||
  450. StrniCmp( pszArgument, _T("-l"), 5) == 0 )
  451. {
  452. /* We change to always log the output
  453. pParams->pfileLog = fopen(c_szLogFileName, "wt");
  454. if( NULL == pParams->pfileLog )
  455. {
  456. //IDS_NETTEST_LOGFILE_ERROR "[ERROR] Cannot open %s to log output!\n"
  457. PrintMessage(pParams, IDS_NETTEST_LOGFILE_ERROR, c_szLogFileName);
  458. return 1;
  459. }
  460. else
  461. {
  462. pParams->fLog = TRUE;
  463. }
  464. */
  465. }
  466. /*$REVIEW (nsun) we won't support problem configuration for NT5.0
  467. else if ( StrniCmp( pszArgument, _T("/problem:"),9) == 0 ||
  468. StrniCmp( pszArgument, _T("-problem:"),9) == 0 )
  469. {
  470. TestName = &pszArgument[9];
  471. i = atoi(TestName);
  472. if ( i > NO_OF_PROBLEMS)
  473. {
  474. printf("Incorrect problem number\n");
  475. exit(0);
  476. }
  477. if (OtherOptions)
  478. goto Usage;
  479. pParams->fProblemBased = TRUE;
  480. pParams->nProblemNumber = i-1;
  481. }
  482. */
  483. else
  484. {
  485. Usage:
  486. // IDS_NETTEST_17000 "\nUsage: %s [/Options]>\n", argv[0] );
  487. // IDS_NETTEST_17001 " /q - Quiet output (errors only)\n" );
  488. // IDS_NETTEST_17002 " /v - Verbose output \n");
  489. // IDS_NETTEST_LOG " /l - Log output to NetDiag.log \n"
  490. // IDS_NETTEST_17003 " /debug - Even more verbose.\n");
  491. // IDS_NETTEST_17004 " /d:<DomainName> - Find a DC in the specified domain.\n");
  492. // IDS_NETTEST_17005 " /fix - fix trivial problems.\n");
  493. // IDS_NETTEST_17006 " /DcAccountEnum - Enumerate DC machine accounts.\n");
  494. // IDS_NETTEST_17007 " /test:<test name> - tests only this test. Non - skippable tests will still be run\n");
  495. // IDS_NETTEST_17008 " Valid tests are :-\n");
  496. PrintMessage(pParams, IDS_NETTEST_17000, argv[0]);
  497. PrintMessage(pParams, IDS_NETTEST_17001);
  498. PrintMessage(pParams, IDS_NETTEST_17002);
  499. PrintMessage(pParams, IDS_NETTEST_LOG);
  500. PrintMessage(pParams, IDS_NETTEST_17003);
  501. PrintMessage(pParams, IDS_NETTEST_17004);
  502. PrintMessage(pParams, IDS_NETTEST_17005);
  503. PrintMessage(pParams, IDS_NETTEST_17006);
  504. PrintMessage(pParams, IDS_NETTEST_17007);
  505. PrintMessage(pParams, IDS_NETTEST_17008);
  506. for ( i =0; i < DimensionOf(s_rgListOfTests); i++)
  507. {
  508. // IDS_GLOBAL_TEST_NAME " %s - %s Test\n"
  509. PrintMessage(pParams, IDS_GLOBAL_TEST_NAME,
  510. s_rgListOfTests[i].pszShortName,
  511. s_rgListOfTests[i].pszLongName);
  512. }
  513. // IDS_GLOBAL_SKIP " /skip:<TestName> - skip the named test. Valid tests are:\n"
  514. PrintMessage( pParams, IDS_GLOBAL_SKIP_OPTION);
  515. for ( i =0; i < DimensionOf(s_rgListOfTests); i++)
  516. {
  517. if ( s_rgListOfTests[i].fSkippable )
  518. {
  519. // IDS_GLOBAL_TEST_NAME " %s - %s Test\n"
  520. PrintMessage( pParams,
  521. IDS_GLOBAL_TEST_NAME,
  522. s_rgListOfTests[i].pszShortName,
  523. s_rgListOfTests[i].pszLongName );
  524. }
  525. }
  526. return 1;
  527. }
  528. }
  529. return 0;
  530. }
  531. int __cdecl
  532. main(
  533. IN int argc,
  534. IN TCHAR ** argv
  535. )
  536. {
  537. int RetVal;
  538. LONG i;
  539. LONG err;
  540. BOOL Failed = FALSE;
  541. int iWSAStatus;
  542. HRESULT hr = hrOK;
  543. NETDIAG_PARAMS Params;
  544. NETDIAG_RESULT Results;
  545. // set the locale to the system default
  546. setlocale( LC_ALL, "");
  547. // Turn on debug checking
  548. // ----------------------------------------------------------------
  549. #ifdef _DEBUG
  550. int tmpFlag;
  551. tmpFlag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
  552. tmpFlag |= _CRTDBG_CHECK_ALWAYS_DF;
  553. tmpFlag |= _CRTDBG_DELAY_FREE_MEM_DF;
  554. tmpFlag |= _CRTDBG_LEAK_CHECK_DF;
  555. // _CrtSetDbgFlag( tmpFlag );
  556. #endif
  557. // Global initialization.
  558. // ----------------------------------------------------------------
  559. RtlZeroMemory( &NlDcZeroGuid, sizeof(NlDcZeroGuid) );
  560. ZeroMemory(&Params, sizeof(NETDIAG_PARAMS));
  561. ZeroMemory(&Results, sizeof(NETDIAG_RESULT));
  562. InitializeListHead( &Results.NetBt.Transports );
  563. // InitializeListHead( &GlobalNetbtTransports );
  564. // InitializeListHead( &GlobalTestedDomains );
  565. InitializeListHead( &Results.Global.listTestedDomains );
  566. // GlobalDnsHostName[0] = 0;
  567. // GlobalDhcpEnabled = FALSE;
  568. // GlobalDnsDomainName = NULL;
  569. // Load the names of all the tests (this is used by the ParseArgs).
  570. // which is why it needs to get loaded first.
  571. // ----------------------------------------------------------------
  572. CheckHr( LoadNamesForListOfTests() );
  573. // Parse input flags.
  574. // ----------------------------------------------------------------
  575. RetVal = ParseArgs( argc, argv, &Params, &Results);
  576. if ( RetVal != 0 )
  577. {
  578. return 1;
  579. }
  580. Params.pfileLog = fopen(c_szLogFileName, "wt");
  581. if( NULL == Params.pfileLog )
  582. {
  583. //IDS_NETTEST_LOGFILE_ERROR "[ERROR] Cannot open %s to log output!\n"
  584. PrintMessage(&Params, IDS_NETTEST_LOGFILE_ERROR, c_szLogFileName);
  585. }
  586. else
  587. {
  588. Params.fLog = TRUE;
  589. }
  590. // Initialize Winsock
  591. // ----------------------------------------------------------------
  592. iWSAStatus = WsaInitialize(&Params, &Results);
  593. if ( iWSAStatus )
  594. {
  595. return 1;
  596. }
  597. /*
  598. if (pParams->fProblemBased) {
  599. for (i =0; i < ListOfProblems[pParams->nProblemNumber].n; i++) {
  600. if ( !(*ListOfProblems[pParams->nProblemNumber].TestProc[i])((PVOID)NULL) )
  601. Failed = TRUE;
  602. }
  603. if (Failed)
  604. PrintMessage(pParams, IDS_GLOBAL_Problem);
  605. else
  606. PrintMessage(pParams, IDS_GLOBAL_NoProblem);
  607. return 0;
  608. }
  609. */
  610. // Get the NetBIOS computer name of this computer
  611. // ----------------------------------------------------------------
  612. CheckHr( GetComputerNameInfo(&Params, &Results) );
  613. // Get the DNS host name and DNS domain.
  614. // ----------------------------------------------------------------
  615. CheckHr( GetDNSInfo(&Params, &Results) );
  616. // Get OS-version info, etc..
  617. // ----------------------------------------------------------------
  618. CheckHr( GetMachineSpecificInfo(&Params, &Results) );
  619. // Other non-ip config info - Rajkumar
  620. // ----------------------------------------------------------------
  621. CheckHr( GetNetBTParameters(&Params, &Results) );
  622. if ( Params.fVerbose )
  623. {
  624. PrintNewLine(&Params, 1);
  625. }
  626. //
  627. // Grab all the information from the registry that 'ipconfig /all'
  628. // would print.
  629. //
  630. // This routine doesn't always return on fatal errors.
  631. //
  632. hr = InitIpconfig(&Params, &Results);
  633. if (!FHrSucceeded(hr))
  634. {
  635. PrintMessage(&Params, IDS_GLOBAL_NoIpCfg);
  636. CheckHr( hr );
  637. }
  638. #ifndef _WIN64
  639. hr = InitIpxConfig(&Params, &Results);
  640. if (!FHrSucceeded(hr))
  641. {
  642. CheckHr( hr );
  643. }
  644. #endif
  645. //
  646. // Determine if any adapter has DHCP enabled.
  647. //
  648. for ( i = 0; i<Results.cNumInterfaces; i++)
  649. {
  650. if (Results.pArrayInterface[i].IpConfig.fActive &&
  651. Results.pArrayInterface[i].IpConfig.pAdapterInfo->DhcpEnabled)
  652. {
  653. Results.IpConfig.fDhcpEnabled = TRUE;
  654. break;
  655. }
  656. }
  657. //if to detect a predefined problem
  658. if (Params.fProblemBased) {
  659. for (i =0; i < ListOfProblems[Params.nProblemNumber].n; i++) {
  660. if ( !(*ListOfProblems[Params.nProblemNumber].TestProc[i])(&Params, &Results) )
  661. Failed = TRUE;
  662. }
  663. if (Failed)
  664. PrintMessage(&Params, IDS_GLOBAL_Problem);
  665. else
  666. PrintMessage(&Params, IDS_GLOBAL_NoProblem);
  667. return 0;
  668. }
  669. //
  670. // Test individual components
  671. //
  672. for ( i=0; i < DimensionOf(s_rgListOfTests); i++ )
  673. {
  674. // If the caller wanted to skip this test,
  675. // do so now.
  676. // ------------------------------------------------------------
  677. if ( s_rgListOfTests[i].fSkipped )
  678. continue;
  679. //We will perform this test
  680. s_rgListOfTests[i].fPerformed = TRUE;
  681. //
  682. // If the test is to be run for each tested domain,
  683. // do so.
  684. //
  685. if ( s_rgListOfTests[i].fPerDomainTest )
  686. {
  687. PTESTED_DOMAIN TestedDomain;
  688. PLIST_ENTRY pListEntry;
  689. //
  690. // Loop through the list of tested domains
  691. //
  692. for ( pListEntry = Results.Global.listTestedDomains.Flink ;
  693. pListEntry != &Results.Global.listTestedDomains ;
  694. pListEntry = pListEntry->Flink ) {
  695. //
  696. // If the entry is found,
  697. // use it.
  698. //
  699. TestedDomain = CONTAINING_RECORD( pListEntry, TESTED_DOMAIN, Next );
  700. Params.pDomain = TestedDomain;
  701. //
  702. // Run this test.
  703. //
  704. if ( FHrFailed((*s_rgListOfTests[i].TestProc)(&Params, &Results))) {
  705. Failed = TRUE;
  706. }
  707. }
  708. //
  709. // If any test failed,
  710. // we're done.
  711. //
  712. if ( Failed ) {
  713. goto Print_Results;
  714. }
  715. //
  716. // If the test is to be run just once,
  717. // do it.
  718. //
  719. } else {
  720. //
  721. // Run this test.
  722. //
  723. if ( FHrFailed((*s_rgListOfTests[i].TestProc)(&Params, &Results)))
  724. {
  725. goto Print_Results;
  726. }
  727. }
  728. }
  729. Print_Results:
  730. // Now that we've run through all of the tests, run through the
  731. // print outs
  732. if (Params.fReallyVerbose)
  733. {
  734. // IDS_GLOBAL_COMPLETE "\n Tests complete.\n\n\n"
  735. PrintMessage( &Params, IDS_GLOBAL_COMPLETE );
  736. }
  737. else
  738. {
  739. PrintNewLine(&Params, 2);
  740. }
  741. DoSystemPrint(&Params, &Results);
  742. DoPerInterfacePrint(&Params, &Results);
  743. DoGlobalPrint(&Params, &Results);
  744. //
  745. // All tests passed.
  746. //
  747. // IDS_GLOBAL_SUCCESS "\nThe command completed successfully\n"
  748. PrintMessage( &Params, IDS_GLOBAL_SUCCESS);
  749. Error:
  750. FreeNamesForListOfTests();
  751. if(Params.pfileLog != NULL && Params.fLog)
  752. {
  753. fclose(Params.pfileLog);
  754. }
  755. ResultsCleanup(&Params, &Results);
  756. return hr != S_OK;
  757. }
  758. HRESULT LoadNamesForListOfTests()
  759. {
  760. int i;
  761. TCHAR szBuffer[256];
  762. for (i=0; i < DimensionOf(s_rgListOfTests); i++)
  763. {
  764. szBuffer[0] = 0;
  765. LoadString(NULL, s_rgListOfTests[i].uIdsShortName, szBuffer,
  766. DimensionOf(szBuffer));
  767. s_rgListOfTests[i].pszShortName = _tcsdup(szBuffer);
  768. szBuffer[0] = 0;
  769. LoadString(NULL, s_rgListOfTests[i].uIdsLongName, szBuffer,
  770. DimensionOf(szBuffer));
  771. s_rgListOfTests[i].pszLongName = StrDup(szBuffer);
  772. }
  773. return hrOK;
  774. }
  775. void FreeNamesForListOfTests()
  776. {
  777. int i;
  778. for (i=0; i < DimensionOf(s_rgListOfTests); i++)
  779. {
  780. Free(s_rgListOfTests[i].pszShortName);
  781. s_rgListOfTests[i].pszShortName = NULL;
  782. Free(s_rgListOfTests[i].pszLongName);
  783. s_rgListOfTests[i].pszLongName = NULL;
  784. }
  785. }
  786. void DoSystemPrint(IN NETDIAG_PARAMS *pParams,
  787. IN NETDIAG_RESULT *pResults)
  788. {
  789. int cInstalled;
  790. int i;
  791. int ids;
  792. PrintMessage(pParams, IDSWSZ_GLOBAL_ComputerName, pResults->Global.swzNetBiosName);
  793. PrintMessage(pParams, IDSSZ_GLOBAL_DnsHostName, pResults->Global.szDnsHostName );
  794. if (pParams->fReallyVerbose)
  795. PrintMessage(pParams, IDSSZ_DnsDomainName,
  796. pResults->Global.pszDnsDomainName);
  797. // " System info : %s (Build %s)\n"
  798. PrintMessage(pParams, IDS_MACHINE_15801,
  799. pResults->Global.pszServerType,
  800. pResults->Global.pszCurrentBuildNumber);
  801. // " Processor : %s\n"
  802. PrintMessage(pParams, IDS_MACHINE_15802,
  803. pResults->Global.pszProcessorInfo);
  804. if (pResults->Global.cHotFixes == 0)
  805. // " Hotfixes : none detected\n"
  806. PrintMessage(pParams, IDS_MACHINE_15803);
  807. else
  808. {
  809. // If in Verbose mode, only print out the hotfixes that are
  810. // installed
  811. if (pParams->fReallyVerbose)
  812. {
  813. // print out a list of all hotfixes
  814. // " Hotfixes :\n"
  815. PrintMessage(pParams, IDS_MACHINE_15804);
  816. // " Installed? Name\n"
  817. PrintMessage(pParams, IDS_MACHINE_15805);
  818. for (i=0; i<pResults->Global.cHotFixes; i++)
  819. {
  820. if (pResults->Global.pHotFixes[i].fInstalled)
  821. ids = IDS_MACHINE_YES_INSTALLED;
  822. else
  823. ids = IDS_MACHINE_NO_INSTALLED;
  824. PrintMessage(pParams, ids,
  825. pResults->Global.pHotFixes[i].pszName);
  826. }
  827. }
  828. else
  829. {
  830. // print out a list of the installed hotfixes
  831. // count the number of installed hotfixes
  832. cInstalled = 0;
  833. for (i=0; i<pResults->Global.cHotFixes; i++)
  834. {
  835. if (pResults->Global.pHotFixes[i].fInstalled)
  836. cInstalled++;
  837. }
  838. if (cInstalled == 0)
  839. {
  840. // " Hotfixes : not hotfixes have been installed\n"
  841. PrintMessage(pParams, IDS_MACHINE_15806);
  842. }
  843. else
  844. {
  845. // " List of installed hotfixes : \n"
  846. PrintMessage(pParams, IDS_MACHINE_15807);
  847. for (i=0; i<pResults->Global.cHotFixes; i++)
  848. {
  849. if (pResults->Global.pHotFixes[i].fInstalled)
  850. {
  851. // " %s\n"
  852. PrintMessage(pParams, IDS_MACHINE_15808, pResults->Global.pHotFixes[i].pszName);
  853. }
  854. }
  855. }
  856. }
  857. }
  858. for ( i=0; i < DimensionOf(s_rgListOfTests); i++ )
  859. {
  860. // If the caller wanted to skip this test,
  861. // do so now.
  862. // ------------------------------------------------------------
  863. if ( s_rgListOfTests[i].fSkipped || !s_rgListOfTests[i].fPerformed)
  864. continue;
  865. if(s_rgListOfTests[i].SystemPrintProc)
  866. s_rgListOfTests[i].SystemPrintProc(pParams, pResults);
  867. }
  868. PrintNewLine(pParams, 1);
  869. }
  870. void DoGlobalPrint(NETDIAG_PARAMS *pParams, NETDIAG_RESULT *pResults)
  871. {
  872. int i;
  873. // IDS_GLOBAL_RESULTS "\nGlobal results\n\n"
  874. PrintMessage( pParams, IDS_GLOBAL_RESULTS );
  875. for ( i=0; i < DimensionOf(s_rgListOfTests); i++ )
  876. {
  877. // If the caller wanted to skip this test,
  878. // do so now.
  879. // ------------------------------------------------------------
  880. if ( s_rgListOfTests[i].fSkipped || !s_rgListOfTests[i].fPerformed)
  881. continue;
  882. if(s_rgListOfTests[i].GlobalPrintProc)
  883. s_rgListOfTests[i].GlobalPrintProc(pParams, pResults);
  884. }
  885. PrintNewLine(pParams, 1);
  886. }
  887. void DoPerInterfacePrint(NETDIAG_PARAMS *pParams,
  888. NETDIAG_RESULT *pResults)
  889. {
  890. int i, iIf;
  891. INTERFACE_RESULT * pIfResult;
  892. //IDS_GLOBAL_INTERFACE_RESULTS "\nPer interface results:\n\n"
  893. PrintMessage( pParams, IDS_GLOBAL_INTERFACE_RESULTS );
  894. // Loop through the interfaces
  895. for ( iIf = 0; iIf < pResults->cNumInterfaces; iIf++)
  896. {
  897. pIfResult = pResults->pArrayInterface + iIf;
  898. if (!pIfResult->fActive)
  899. continue;
  900. PrintNewLine(pParams, 1);
  901. // Print out the interface name
  902. PrintMessage(pParams, IDSSZ_IPCFG_Adapter,
  903. pResults->pArrayInterface[iIf].pszFriendlyName ?
  904. pResults->pArrayInterface[iIf].pszFriendlyName :
  905. MapGuidToAdapterName(pIfResult->IpConfig.pAdapterInfo->AdapterName));
  906. if (pParams->fReallyVerbose)
  907. PrintMessage(pParams, IDS_IPCFG_10004,
  908. pResults->pArrayInterface[iIf].pszName);
  909. for ( i=0; i < DimensionOf(s_rgListOfTests); i++ )
  910. {
  911. // If the caller wanted to skip this test,
  912. // do so now.
  913. // ------------------------------------------------------------
  914. if ( s_rgListOfTests[i].fSkipped || !s_rgListOfTests[i].fPerformed )
  915. continue;
  916. s_rgListOfTests[i].PerInterfacePrintProc(pParams, pResults,
  917. pIfResult);
  918. }
  919. fflush(stdout);
  920. }
  921. }