Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5534 lines
139 KiB

  1. /*++ Copyright(c) 2001 Microsoft Corporation
  2. Module Name:
  3. NLB Manager
  4. File Name:
  5. tprov.cpp
  6. Abstract:
  7. Test harness for nlb manager provider code
  8. History:
  9. 04/08/01 JosephJ Created
  10. --*/
  11. #include "tprov.h"
  12. #include "tprov.tmh"
  13. BOOL g_Silent = FALSE;
  14. HANDLE g_hEventLog = NULL; // defined here to get ..\updatecf.cpp to link ok.
  15. BOOL g_Impersonate=FALSE;
  16. int g_nRetCode = 0; // return code for this program.
  17. #define RETCODE_NO_ERROR 0
  18. #define RETCODE_UPDATE_FAILED 1
  19. #define RETCODE_NEW_CONFIG_DOESNT_MATCH 2
  20. HMODULE ghModule;
  21. void test_alignment(void);
  22. void test_local_logger(void);
  23. void test_encrypt_memory(void);
  24. BOOL
  25. GetPassword(
  26. PWSTR szBuffer,
  27. DWORD dwLength,
  28. DWORD *pdwLengthReturn
  29. );
  30. #define ARRAY_LENGTH(_array) (sizeof(_array)/sizeof(_array[0]))
  31. typedef enum
  32. {
  33. DO_USAGE,
  34. DO_WMINICLIST,
  35. DO_NICLIST,
  36. DO_IPADDR,
  37. DO_NLBCFG,
  38. DO_NLBBIND,
  39. DO_UPDATE,
  40. DO_WMIUPDATE,
  41. DO_CLEANREG
  42. } COMMAND_TYPE;
  43. typedef enum
  44. {
  45. KW_ADAPTER_LIST,
  46. KW_UPDATE,
  47. KW_QUIT,
  48. KW_HELP,
  49. KW_ADAPTER_GUID,
  50. KW_NETWORK_ADDRESSES,
  51. KW_PARTIAL_UPDATE,
  52. KW_NLB_BOUND,
  53. KW_CLUSTER_NETWORK_ADDRESS,
  54. KW_CLUSTER_NAME,
  55. KW_TRAFFIC_MODE,
  56. KW_PORT_RULES,
  57. KW_HOST_PRIORITY,
  58. KW_DEDICATED_NETWORK_ADDRESS,
  59. KW_CLUSTER_MODE_ON_START,
  60. KW_PERSIST_SUSPEND_ON_REBOOT,
  61. KW_REMOTE_CONTROL_ENABLED,
  62. KW_PASSWORD,
  63. KW_LIST,
  64. KW_DOT,
  65. KW_MODIFY_NETWORK_ADDRESS,
  66. KW_IPADDR, // test command
  67. KW_NLBBIND, // test command
  68. KW_NLBCFG, // test command
  69. KW_YES,
  70. KW_NO,
  71. //
  72. // Control cluster/port related
  73. //
  74. KW_CONTROL,
  75. KW_START,
  76. KW_STOP,
  77. KW_DRAIN_STOP,
  78. KW_SUSPEND,
  79. KW_RESUME,
  80. KW_ENABLE,
  81. KW_DISABLE,
  82. KW_DRAIN,
  83. KW_QUERY,
  84. KW_VIP,
  85. KW_PORT,
  86. KW_MAIN_SHELL, // implicit keyword if no command present in cmdline.
  87. KW_UNKNOWN
  88. } KEYWORD;
  89. VOID do_usage(VOID);
  90. VOID do_niclist(LPCWSTR szFriendlyName, LPWSTR *pszGuid);
  91. VOID do_wminiclist(LPCWSTR szFriendlyName, LPWSTR *pszGuid);
  92. VOID do_ipaddr(VOID);
  93. VOID do_nlbcfg(VOID);
  94. VOID do_nlbbind(VOID);
  95. VOID do_update(VOID);
  96. VOID do_wmiupdate(VOID);
  97. VOID do_cleanreg(VOID);
  98. void parse_main(int argc, WCHAR* argv[]);
  99. VOID test_add_ips(LPCWSTR szNic);
  100. VOID test_bind_nlb(LPCWSTR szNic);
  101. VOID test_cfg_nlb(LPCWSTR szNic);
  102. VOID test_update(LPCWSTR szMachine, LPCWSTR szNic);
  103. void test(int argc, WCHAR* argv[]);
  104. void test(int argc, WCHAR* argv[]);
  105. void test_safearray(void);
  106. VOID test_exfcfgclass(void);
  107. void test_read_keyword(void);
  108. VOID test_port_rule_string(VOID);
  109. void test_vectors(void);
  110. void test_maps(void);
  111. void test_validate_network_address(void);
  112. void test_nlbipaddresslist(void);
  113. void test_ioctl_alignment(void);
  114. BOOL read_guid(LPWSTR *pszNic);
  115. BOOL read_machinename(LPWSTR *pszNic);
  116. BOOL read_password(VOID);
  117. BOOL get_guid_by_friendly_name(VOID);
  118. BOOL valid_guid(LPCWSTR szGuid);
  119. KEYWORD
  120. parse_args(int argc, WCHAR* argv[]);
  121. typedef struct
  122. {
  123. KEYWORD kw;
  124. LPCWSTR sz;
  125. } KEYWORD_MAP;
  126. const KEYWORD_MAP KeywordMap[] =
  127. {
  128. {KW_ADAPTER_LIST, L"AdapterList"},
  129. {KW_ADAPTER_LIST, L"AL"},
  130. {KW_QUIT, L"Quit"},
  131. {KW_QUIT, L"Q"},
  132. {KW_UPDATE, L"Update"},
  133. {KW_UPDATE, L"U"},
  134. {KW_HELP, L"Help"},
  135. {KW_HELP, L"H"},
  136. {KW_HELP, L"?"},
  137. {KW_ADAPTER_GUID, L"AdapterGuid"},
  138. {KW_ADAPTER_GUID, L"AG"},
  139. {KW_NETWORK_ADDRESSES, L"NetworkAddresses"},
  140. {KW_NETWORK_ADDRESSES, L"NA"},
  141. {KW_PARTIAL_UPDATE, L"PartialUpdate"},
  142. {KW_PARTIAL_UPDATE, L"PU"},
  143. {KW_NLB_BOUND, L"NlbBound"},
  144. {KW_NLB_BOUND, L"NB"},
  145. {KW_CLUSTER_NETWORK_ADDRESS, L"ClusterNetworkAddress"},
  146. {KW_CLUSTER_NETWORK_ADDRESS, L"CNA"},
  147. {KW_CLUSTER_NAME, L"ClusterName"},
  148. {KW_CLUSTER_NAME, L"CN"},
  149. {KW_TRAFFIC_MODE, L"TrafficMode"},
  150. {KW_TRAFFIC_MODE, L"TM"},
  151. {KW_PORT_RULES, L"PortRules"},
  152. {KW_PORT_RULES, L"PR"},
  153. {KW_HOST_PRIORITY, L"HostPriority"},
  154. {KW_HOST_PRIORITY, L"HP"},
  155. {KW_DEDICATED_NETWORK_ADDRESS, L"DedicatedNetworkAddress"},
  156. {KW_DEDICATED_NETWORK_ADDRESS, L"DNA"},
  157. {KW_CLUSTER_MODE_ON_START, L"ClusterModeOnStart"},
  158. {KW_CLUSTER_MODE_ON_START, L"CMOS"},
  159. {KW_PERSIST_SUSPEND_ON_REBOOT, L"PersistSuspend"},
  160. {KW_PERSIST_SUSPEND_ON_REBOOT, L"PS"},
  161. {KW_REMOTE_CONTROL_ENABLED, L"RemoteControlEnabled"},
  162. {KW_REMOTE_CONTROL_ENABLED, L"RCE"},
  163. {KW_PASSWORD, L"Password"},
  164. {KW_PASSWORD, L"P"},
  165. {KW_LIST, L"List"},
  166. {KW_LIST, L"L"},
  167. {KW_DOT, L"."},
  168. {KW_MODIFY_NETWORK_ADDRESS, L"ModifyNetworkAddress"},
  169. {KW_MODIFY_NETWORK_ADDRESS, L"MNA"},
  170. {KW_IPADDR, L"ipaddr"}, // test command -- only cmdline param
  171. {KW_NLBBIND, L"nlbbind"}, // test command -- only cmdline param
  172. {KW_NLBCFG, L"nlbcfg"}, // test command -- only cmdline param
  173. {KW_YES, L"yes"},
  174. {KW_YES, L"y"},
  175. {KW_NO, L"no"},
  176. {KW_NO, L"n"},
  177. //
  178. // Control cluster/port related
  179. //
  180. {KW_CONTROL, L"control"},
  181. {KW_CONTROL, L"cl"},
  182. {KW_START, L"start"},
  183. {KW_START, L"st"},
  184. {KW_STOP, L"stop"},
  185. {KW_STOP, L"sp"},
  186. {KW_DRAIN_STOP, L"drainstop"},
  187. {KW_DRAIN_STOP, L"ds"},
  188. {KW_SUSPEND, L"suspend"},
  189. {KW_SUSPEND, L"su"},
  190. {KW_RESUME, L"resume"},
  191. {KW_RESUME, L"re"},
  192. {KW_ENABLE, L"enable"},
  193. {KW_ENABLE, L"en"},
  194. {KW_DISABLE, L"disable"},
  195. {KW_DISABLE, L"di"},
  196. {KW_DRAIN, L"drain"},
  197. {KW_DRAIN, L"dn"},
  198. {KW_QUERY, L"query"},
  199. {KW_QUERY, L"qu"},
  200. {KW_VIP, L"vip"},
  201. {KW_PORT, L"port"},
  202. {KW_UNKNOWN, NULL} // Must be last
  203. };
  204. KEYWORD parse_adapter_list(VOID);
  205. KEYWORD parse_update(VOID);
  206. KEYWORD parse_main_help(VOID);
  207. KEYWORD lookup_keyword(LPCWSTR szKeyword);
  208. struct
  209. {
  210. // *_LENGTH ==> doesn't include space for ending NULL
  211. #define MAX_MACHINE_NAME_LENGTH 256
  212. #define MAX_USER_NAME_LENGTH 256
  213. #define MAX_PASSWORD_LENGTH 256
  214. #define INPUT_BUFFER_LENGTH 1024
  215. #define NLB_MAX_FRIENDLY_NAME_LENGTH 256
  216. WCHAR MachineName[MAX_MACHINE_NAME_LENGTH+1];
  217. WCHAR UserName[MAX_USER_NAME_LENGTH+1];
  218. WCHAR Password[MAX_PASSWORD_LENGTH+1];
  219. WCHAR InputBuffer[INPUT_BUFFER_LENGTH+1];
  220. WCHAR AdapterGuid[NLB_GUID_STRING_SIZE];
  221. WCHAR FriendlyName[NLB_MAX_FRIENDLY_NAME_LENGTH+1];
  222. BOOL fReadPassword;
  223. BOOL fUseWmi;
  224. BOOL fLocalHost;
  225. BOOL fGotGuid;
  226. BOOL fGotFriendlyName;
  227. BOOL fRunOnce;
  228. } g;
  229. void
  230. display_config(
  231. LPCWSTR szNicGuid,
  232. NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg
  233. );
  234. void
  235. display_port_rules(
  236. NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg
  237. );
  238. void
  239. display_config2(
  240. LPCWSTR szNicGuid,
  241. NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg
  242. );
  243. VOID
  244. display_ip_info(
  245. IN UINT NumIpAddresses,
  246. IN NLB_IP_ADDRESS_INFO *pIpInfo
  247. );
  248. VOID
  249. display_ip_info2(
  250. IN UINT NumIpAddresses,
  251. IN NLB_IP_ADDRESS_INFO *pIpInfo
  252. );
  253. WBEMSTATUS
  254. read_ip_info(
  255. IN LPCWSTR szNic,
  256. OUT UINT *pNumIpAddresses,
  257. OUT NLB_IP_ADDRESS_INFO **ppIpInfo
  258. );
  259. BOOL
  260. WINAPI
  261. MyCtrlHandlerRoutine(
  262. DWORD dwCtrlType // control signal type
  263. )
  264. {
  265. //
  266. // We de-initialize here so that we don't get an AV when the user types
  267. // CtrlC
  268. //
  269. CfgUtilDeitialize();
  270. return FALSE;
  271. }
  272. int __cdecl wmain(int argc, WCHAR* argv[], WCHAR* envp[])
  273. {
  274. (void) SetConsoleCtrlHandler(
  275. MyCtrlHandlerRoutine, // handler function
  276. TRUE // TRUE== add
  277. );
  278. //
  279. // Enable tracing
  280. //
  281. WPP_INIT_TRACING(L"Microsoft\\NLB\\TPROV");
  282. ghModule = GetModuleHandle(NULL);
  283. #if 0
  284. test_encrypt_memory();
  285. // test_local_logger();
  286. // test_alignment();
  287. // test_port_rule_string();
  288. // test_safearray();
  289. // test_tmgr(argc, argv);
  290. // test_exfcfgclass();
  291. // test_vectors();
  292. // test_maps();
  293. // test_validate_network_address();
  294. // test_read_keyword();
  295. // test_nlbipaddresslist();
  296. // test_ioctl_alignment();
  297. #else
  298. // NlbHostFake();
  299. //
  300. // Enable the "SeLoadDriverPrivilege" privilege in the process access token.
  301. // This is needed in the case when the server is local (ie. same machine).
  302. // Do NOT check for the return value since this function will fail when called
  303. // as a non-admin. It is not only ok but also necessary to ignore the failure of
  304. // this function because:
  305. // 1. We already check in the wmi provider that the caller is an administrator on
  306. // the server and if the privilege is enabled. This is why it is ok to ignore
  307. // failures in this function.
  308. // 2. Non-admins can run nlb manager. They only need to be admins on the server.
  309. // This is why it is necessary to ignore failures in this function.
  310. //
  311. CfgUtils_Enable_Load_Unload_Driver_Privilege();
  312. CfgUtilInitialize(
  313. TRUE, // TRUE == init as server (use wlbsctrl apis if pos)
  314. FALSE // FALSE == Do not disable Ping (i.e, enable ping)
  315. );
  316. NlbConfigurationUpdate::StaticInitialize();
  317. parse_main(argc, argv);
  318. NlbConfigurationUpdate::PrepareForDeinitialization();
  319. NlbConfigurationUpdate::StaticDeinitialize();
  320. CfgUtilDeitialize();
  321. #endif
  322. //
  323. // Disable tracing
  324. //
  325. WPP_CLEANUP();
  326. return g_nRetCode;
  327. }
  328. NLB_EXTENDED_CLUSTER_CONFIGURATION MyOldCfg;
  329. NLB_EXTENDED_CLUSTER_CONFIGURATION MyNewCfg;
  330. VOID
  331. display_log(WCHAR *pLog)
  332. {
  333. static UINT previous_length;
  334. UINT current_length;
  335. current_length = wcslen(pLog);
  336. if (previous_length > current_length)
  337. {
  338. previous_length = 0;
  339. }
  340. wprintf(L"%ws", pLog+previous_length);
  341. previous_length = current_length;
  342. }
  343. LPCWSTR NicGuids[] = {
  344. L"{AD4DA14D-CAAE-42DD-97E3-5355E55247C2}",
  345. L"{B2CD5533-5091-4F49-B80F-A07844B14209}",
  346. L"{EBE09517-07B4-4E88-AAF1-E06F5540608B}",
  347. L"{ABEA4318-5EE8-4DEC-AF3C-B4AEDE61454E}",
  348. L"{66A1869A-BF85-4D95-BBAB-07FA5B4449D4}",
  349. L"{AEEE83AF-AA48-4599-94BB-7C458D63CEED}",
  350. L"{D0536EEE-2CE0-4E8D-BFEC-0A608CFD81B9}"
  351. };
  352. UINT Trial;
  353. void test(int argc, WCHAR* argv[])
  354. {
  355. KEYWORD cmd;
  356. cmd = parse_args(argc, argv);
  357. switch(cmd)
  358. {
  359. case KW_UNKNOWN: do_usage();
  360. break;
  361. case KW_ADAPTER_LIST: do_niclist(NULL, NULL);
  362. break;
  363. case KW_IPADDR: do_ipaddr();
  364. break;
  365. case KW_NLBCFG: do_nlbcfg();
  366. break;
  367. case KW_NLBBIND: do_nlbbind();
  368. break;
  369. case KW_UPDATE: do_update();
  370. break;
  371. #if 0
  372. case KW_WMINICLIST: do_wminiclist(NULL, NULL);
  373. break;
  374. case KW_WMIUPDATE: do_wmiupdate();
  375. break;
  376. case KW_CLEANREG: do_cleanreg();
  377. break;
  378. #endif // 0
  379. }
  380. return;
  381. }
  382. void
  383. display_config(
  384. LPCWSTR szNicGuid,
  385. NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg
  386. )
  387. {
  388. LPWSTR szFriendlyName = NULL;
  389. if (g_Silent) return;
  390. WBEMSTATUS Status;
  391. Status = pCfg->GetFriendlyName(&szFriendlyName);
  392. if (FAILED(Status))
  393. {
  394. szFriendlyName = NULL;
  395. }
  396. printf(
  397. "\nNLB Configuration for %ws \"%ws\" %ws\n",
  398. szNicGuid,
  399. (szFriendlyName == NULL) ? L"" : szFriendlyName,
  400. pCfg->fDHCP ? L"(DHCP)" : L""
  401. );
  402. printf("\tfValidNlbCfg=%d\n", pCfg->fValidNlbCfg);
  403. printf("\tGeneration=%d\n", pCfg->Generation);
  404. printf("\tfBound=%d\n", pCfg->fBound);
  405. printf("\tfAddDedicatedIp=%d\n", pCfg->fAddDedicatedIp);
  406. UINT AddrCount = pCfg->NumIpAddresses;
  407. display_ip_info(AddrCount, pCfg->pIpAddressInfo);
  408. if (pCfg->fBound)
  409. {
  410. printf("\n");
  411. printf("\tNLB configuration:\n");
  412. if (pCfg->fValidNlbCfg)
  413. {
  414. printf("\t\tClusterIP: {%ws,%ws}\n",
  415. pCfg->NlbParams.cl_ip_addr,
  416. pCfg->NlbParams.cl_net_mask
  417. );
  418. printf("\t\tDedicatedIP: {%ws,%ws}\n",
  419. pCfg->NlbParams.ded_ip_addr,
  420. pCfg->NlbParams.ded_net_mask
  421. );
  422. }
  423. else
  424. {
  425. printf("**invalid configuration**\n");
  426. }
  427. }
  428. printf("\n");
  429. delete szFriendlyName;
  430. szFriendlyName = NULL;
  431. return;
  432. }
  433. LPCWSTR bool_string(BOOL b)
  434. {
  435. return b ? L"true" : L"false";
  436. }
  437. void
  438. display_config2(
  439. LPCWSTR szNicGuid,
  440. NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg
  441. )
  442. {
  443. LPWSTR szFriendlyName = NULL;
  444. if (g_Silent) return;
  445. WBEMSTATUS Status;
  446. Status = pCfg->GetFriendlyName(&szFriendlyName);
  447. if (FAILED(Status))
  448. {
  449. szFriendlyName = NULL;
  450. }
  451. printf(
  452. "\nNLB Configuration for %ws \"%ws\"%ws\n",
  453. szNicGuid,
  454. (szFriendlyName == NULL) ? L"" : szFriendlyName,
  455. pCfg->fDHCP ? L" (DHCP)" : L""
  456. );
  457. // printf(" fValidNlbCfg=%d\n", pCfg->fValidNlbCfg);
  458. // printf(" fAddDedicatedIp=%d\n", pCfg->fAddDedicatedIp);
  459. printf(" Generation = %d\n", pCfg->Generation);
  460. wprintf(L" NlbBound = %ws\n", bool_string(pCfg->fBound));
  461. UINT AddrCount = pCfg->NumIpAddresses;
  462. display_ip_info2(AddrCount, pCfg->pIpAddressInfo);
  463. if (pCfg->fBound)
  464. {
  465. if (pCfg->fValidNlbCfg)
  466. {
  467. LPWSTR sz = NULL;
  468. printf(" ClusterNetworkAddress = %ws/%ws\n",
  469. pCfg->NlbParams.cl_ip_addr,
  470. pCfg->NlbParams.cl_net_mask
  471. );
  472. // cluster_name
  473. Status = pCfg->GetClusterName(&sz);
  474. if (FAILED(Status))
  475. {
  476. sz = NULL;
  477. }
  478. else
  479. {
  480. printf(" ClusterName = %ws\n", sz);
  481. delete sz;
  482. sz = NULL;
  483. }
  484. // traffic_mode
  485. {
  486. LPCWSTR szMode = NULL;
  487. switch(pCfg->GetTrafficMode())
  488. {
  489. case NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_UNICAST:
  490. szMode = L"UNICAST";
  491. break;
  492. case NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_MULTICAST:
  493. szMode = L"MULTICAST";
  494. break;
  495. case NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_IGMPMULTICAST:
  496. szMode = L"IGMPMULTICAST";
  497. break;
  498. default:
  499. assert(FALSE);
  500. szMode = L"*unknown mode*";
  501. }
  502. wprintf(L" TrafficMode = %ws\n", szMode);
  503. }
  504. // port_rules
  505. display_port_rules(pCfg);
  506. // host_priority
  507. wprintf(L" HostPriority = %lu\n", pCfg->GetHostPriority());
  508. printf(" DedicatedNetworkAddress = %ws/%ws\n",
  509. pCfg->NlbParams.ded_ip_addr,
  510. pCfg->NlbParams.ded_net_mask
  511. );
  512. // cluster_mode_on_start
  513. DWORD ClusterModeOnStart = pCfg->GetClusterModeOnStart();
  514. if (ClusterModeOnStart == CVY_HOST_STATE_STARTED)
  515. {
  516. wprintf(L" ClusterModeOnStart = %ws\n", L"true");
  517. }
  518. else if (ClusterModeOnStart == CVY_HOST_STATE_STOPPED)
  519. {
  520. wprintf(L" ClusterModeOnStart = %ws\n", L"false");
  521. }
  522. else // suspend
  523. {
  524. wprintf(L" ClusterModeOnStart = %ws\n", L"suspend");
  525. }
  526. // persist_suspend_on_reboot
  527. if (pCfg->GetPersistSuspendOnReboot() == TRUE)
  528. {
  529. wprintf(L" PersistSuspend = %ws\n", L"true");
  530. }
  531. else
  532. {
  533. wprintf(L" PersistSuspend = %ws\n", L"false");
  534. }
  535. // remote_control_enabled
  536. wprintf(L" RemoteControlEnabled = %ws\n",
  537. bool_string(pCfg->GetRemoteControlEnabled()));
  538. }
  539. else
  540. {
  541. printf("NLB configuration is invalid\n");
  542. }
  543. }
  544. printf("\n");
  545. delete szFriendlyName;
  546. szFriendlyName = NULL;
  547. return;
  548. }
  549. void
  550. display_port_rules(
  551. NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg
  552. )
  553. {
  554. WBEMSTATUS Status;
  555. LPWSTR *pszPortRules = NULL;
  556. UINT NumPortRules = 0;
  557. Status = pCfg->GetPortRules(&pszPortRules, &NumPortRules);
  558. if (FAILED(Status))
  559. {
  560. wprintf(L" PortRules = *invalid*\n");
  561. pszPortRules = NULL;
  562. goto end;
  563. }
  564. if (NumPortRules)
  565. {
  566. wprintf(L" PortRules =\n {\n");
  567. for (UINT u=0; u<NumPortRules; u++)
  568. {
  569. wprintf(
  570. L" %ws%ws\n",
  571. pszPortRules[u],
  572. u==(NumPortRules-1) ? L"" : L","
  573. );
  574. }
  575. wprintf(L" }\n");
  576. }
  577. else
  578. {
  579. wprintf(L" PortRules = {}\n");
  580. }
  581. end:
  582. delete pszPortRules;
  583. }
  584. VOID
  585. test_add_ips(LPCWSTR szNic)
  586. //
  587. // Go through a set of IPs on this NIC
  588. //
  589. {
  590. WBEMSTATUS Status = WBEM_NO_ERROR;
  591. UINT NumIpAddresses= 0;
  592. NLB_IP_ADDRESS_INFO *pIpInfo = NULL;
  593. while(1)
  594. {
  595. //
  596. // Get the current list of ip addresses
  597. //
  598. Status = CfgUtilGetIpAddressesAndFriendlyName(
  599. szNic,
  600. &NumIpAddresses,
  601. &pIpInfo,
  602. NULL // szFriendly name
  603. );
  604. if (FAILED(Status))
  605. {
  606. printf("Error 0x%08lx getting ip address list for %ws\n",
  607. (UINT) Status, szNic);
  608. pIpInfo = NULL;
  609. goto end;
  610. }
  611. //
  612. // display what we find.
  613. //
  614. display_ip_info(NumIpAddresses, pIpInfo);
  615. if (pIpInfo!=NULL)
  616. {
  617. delete pIpInfo;
  618. pIpInfo = NULL;
  619. }
  620. //
  621. // Read the list ip address and subnet masks from the input
  622. //
  623. Status = read_ip_info(szNic, &NumIpAddresses, &pIpInfo);
  624. if (FAILED(Status))
  625. {
  626. printf("Quitting test_add_ips\n");
  627. break;
  628. }
  629. //
  630. // Set the specified IPs
  631. //
  632. 1 && (Status = CfgUtilSetStaticIpAddresses(
  633. szNic,
  634. NumIpAddresses,
  635. pIpInfo
  636. ));
  637. if (FAILED(Status))
  638. {
  639. printf("CfgUtilSetStaticIpAddresses failed with status 0x%08lx\n",
  640. Status);
  641. }
  642. else
  643. {
  644. printf("Successfully set the specified IPs on the NIC\n");
  645. }
  646. }
  647. end:
  648. if (pIpInfo != NULL)
  649. {
  650. delete pIpInfo;
  651. }
  652. }
  653. VOID
  654. test_bind_nlb(LPCWSTR szNic)
  655. {
  656. WBEMSTATUS Status;
  657. BOOL fBound = FALSE;
  658. printf("\nRunning bind/unbind test for NIC %ws...\n\n", szNic);
  659. while(1)
  660. {
  661. //
  662. // Check NLB bind state
  663. //
  664. printf("Checking if NLB is bound...\n");
  665. Status = CfgUtilCheckIfNlbBound(szNic, &fBound);
  666. if (FAILED(Status))
  667. {
  668. printf("CfgUtilCheckIfNlbBound fails with error 0x%08lx\n", (UINT)Status);
  669. break;
  670. }
  671. printf(
  672. "NLB is %wsbound\n\n",
  673. (fBound) ? L"" : L"NOT "
  674. );
  675. printf("Enter 'b' to bind, 'u' to unbind or 'q' to quit\n:");
  676. WCHAR Temp[32] = L"";
  677. while (wscanf(L" %1[buq]", Temp)!=1)
  678. {
  679. printf("Incorrect input. Try again.\n");
  680. if (feof(stdin))
  681. {
  682. *Temp = 'q';
  683. break;
  684. }
  685. }
  686. if (*Temp == 'b')
  687. {
  688. printf("Attempting to bind NLB...\n");
  689. fBound = TRUE;
  690. }
  691. else if (*Temp == 'u')
  692. {
  693. printf("Attempting to unbind NLB\n");
  694. fBound = FALSE;
  695. }
  696. else
  697. {
  698. printf("Quitting\n");
  699. break;
  700. }
  701. #if 1
  702. Status = CfgUtilChangeNlbBindState(szNic, fBound);
  703. if (FAILED(Status))
  704. {
  705. printf("CfgUtilChangeNlbBindState fails with error %08lx\n",
  706. (UINT) Status);
  707. }
  708. else
  709. {
  710. printf(
  711. "%ws completed successfully\n",
  712. (fBound) ? L"Bind" : L"Unbind"
  713. );
  714. }
  715. #endif // 0
  716. printf("\n");
  717. }
  718. }
  719. VOID
  720. test_cfg_nlb(LPCWSTR szNic)
  721. {
  722. WBEMSTATUS Status;
  723. printf("\nRunning update NLB config test for NIC %ws...\n\n", szNic);
  724. while (1)
  725. {
  726. WLBS_REG_PARAMS Params;
  727. ZeroMemory(&Params, sizeof(Params));
  728. //
  729. // Read NLB config
  730. //
  731. Status = CfgUtilGetNlbConfig(szNic, &Params);
  732. if (FAILED(Status))
  733. {
  734. printf("CfgUtilGetNlbConfig fails with error 0x%08lx\n", (UINT)Status);
  735. break;
  736. }
  737. printf("NLB configuration:\n");
  738. printf(
  739. "\tClusterIP: {%ws,%ws}\n",
  740. Params.cl_ip_addr,
  741. Params.cl_net_mask
  742. );
  743. //
  744. // Make some modifications
  745. //
  746. printf("\nEnter new {cluster-ip-addr,subnet-mask} or 'q' to quit\n:");
  747. while(1)
  748. {
  749. NLB_IP_ADDRESS_INFO Info;
  750. INT i = wscanf(
  751. L" { %15[0-9.] , %15[0-9.] }",
  752. Info.IpAddress,
  753. Info.SubnetMask
  754. );
  755. if (i!=2)
  756. {
  757. WCHAR Temp[100] = L"";
  758. if ( (wscanf(L"%64ws", Temp) == 1)
  759. && !_wcsicmp(Temp, L"q"))
  760. {
  761. printf("Quitting\n");
  762. goto end;
  763. }
  764. else if (feof(stdin))
  765. {
  766. goto end;
  767. }
  768. else
  769. {
  770. printf("Badly formed input. Try again\n");
  771. }
  772. }
  773. else
  774. {
  775. ARRAYSTRCPY(Params.cl_ip_addr, Info.IpAddress);
  776. ARRAYSTRCPY(Params.cl_net_mask, Info.SubnetMask);
  777. break;
  778. }
  779. }
  780. //
  781. // Write NLB config
  782. //
  783. #if 1
  784. printf("\nAttempting to update NLB configuration...\n");
  785. Status = CfgUtilSetNlbConfig(szNic, &Params, FALSE); // FALSE==old bind
  786. if (FAILED(Status))
  787. {
  788. printf("CfgUtilSetNlbConfig fails with error %08lx\n",
  789. (UINT) Status);
  790. }
  791. else
  792. {
  793. printf("change completed successfully\n");
  794. }
  795. #endif // 0
  796. printf("\n");
  797. }
  798. end:
  799. return;
  800. }
  801. VOID
  802. test_update(
  803. LPCWSTR szMachineName, // NULL == don't use wmi
  804. LPCWSTR szNicGuid
  805. )
  806. {
  807. WBEMSTATUS Status;
  808. WCHAR *pLog = NULL;
  809. WBEMSTATUS CompletionStatus;
  810. UINT Generation;
  811. WMI_CONNECTION_INFO ConnInfo;
  812. ZeroMemory(&ConnInfo, sizeof(ConnInfo));
  813. ConnInfo.szMachine = szMachineName;
  814. printf("\nRunning high-level update NLB config test for NIC %ws...\n\n", szNicGuid);
  815. while(1)
  816. {
  817. BOOL fSetDefaults = FALSE;
  818. UINT NumIpAddresses = 0;
  819. NLB_IP_ADDRESS_INFO *pIpInfo = NULL;
  820. BOOL fUnbind = FALSE;
  821. //
  822. // Clean up config info
  823. //
  824. if (MyOldCfg.pIpAddressInfo!=NULL)
  825. {
  826. delete MyOldCfg.pIpAddressInfo;
  827. }
  828. ZeroMemory(&MyOldCfg, sizeof(MyOldCfg));
  829. if (MyNewCfg.pIpAddressInfo!=NULL)
  830. {
  831. delete MyNewCfg.pIpAddressInfo;
  832. }
  833. ZeroMemory(&MyNewCfg, sizeof(MyNewCfg));
  834. printf("TEST: Going to get configuration for NIC %ws\n", szNicGuid);
  835. MyBreak(L"Break before calling GetConfiguration.\n");
  836. if (szMachineName==NULL)
  837. {
  838. Status = NlbConfigurationUpdate::GetConfiguration(
  839. szNicGuid,
  840. &MyOldCfg
  841. );
  842. }
  843. else
  844. {
  845. Status = NlbHostGetConfiguration(
  846. &ConnInfo,
  847. szNicGuid,
  848. &MyOldCfg
  849. );
  850. }
  851. if (FAILED(Status))
  852. {
  853. goto end;
  854. }
  855. display_config(szNicGuid, &MyOldCfg);
  856. if (MyOldCfg.fBound)
  857. {
  858. printf("\nEnter 2 or more {cluster-ip-addr,subnet-mask} or none to unbind or 'q' to quit. The first entry is the dedicated-ip.\n");
  859. if (!MyOldCfg.fValidNlbCfg)
  860. {
  861. //
  862. // We're bound, but nlb params are bad. Set defaults.
  863. //
  864. fSetDefaults = TRUE;
  865. }
  866. }
  867. else
  868. {
  869. //
  870. // We're previously unbound. Set defaults.
  871. //
  872. fSetDefaults = TRUE;
  873. printf("\nEnter 2 or more {cluster-ip-addr,subnet-mask} or 'q' to quit. The first entry is the dedicated-ip.\n");
  874. }
  875. while(1)
  876. {
  877. //
  878. // Read the list ip address and subnet masks from the input
  879. //
  880. Status = read_ip_info(szNicGuid, &NumIpAddresses, &pIpInfo);
  881. if (FAILED(Status))
  882. {
  883. printf("Quitting\n");
  884. goto end;
  885. }
  886. if (NumIpAddresses < 2)
  887. {
  888. if (MyOldCfg.fBound)
  889. {
  890. if (NumIpAddresses == 0)
  891. {
  892. fUnbind = TRUE;
  893. break;
  894. }
  895. else
  896. {
  897. printf("Wrong number of IP addresses -- enter either 0 or >= 2.\n");
  898. }
  899. }
  900. else
  901. {
  902. printf("Wrong number of IP addresses. Enter >= 2 IP addresses.");
  903. }
  904. }
  905. else
  906. {
  907. //
  908. // >= 2 addresses. First one is the dip and the 2nd is the vip.
  909. //
  910. break;
  911. }
  912. if (pIpInfo != NULL)
  913. {
  914. delete pIpInfo;
  915. pIpInfo = NULL;
  916. }
  917. }
  918. if (fUnbind)
  919. {
  920. //
  921. // We're to unbind.
  922. //
  923. ZeroMemory(&MyNewCfg, sizeof(MyNewCfg));
  924. MyNewCfg.fValidNlbCfg = TRUE;
  925. MyNewCfg.fBound = FALSE;
  926. //
  927. // Set the list of ip address to have present on unbind to
  928. // be the dedicated ip address, if there is one, otherwise zero,
  929. // in which case the adapter will be switched to DHCP after NLB
  930. // is unbound
  931. //
  932. if (MyOldCfg.NlbParams.ded_ip_addr[0]!=0)
  933. {
  934. NLB_IP_ADDRESS_INFO *pTmpIpInfo;
  935. pTmpIpInfo = new NLB_IP_ADDRESS_INFO;
  936. if (pTmpIpInfo == NULL)
  937. {
  938. printf("TEST: allocation failure; can't add IP on unbind.\n");
  939. }
  940. else
  941. {
  942. ARRAYSTRCPY(pTmpIpInfo->IpAddress, MyOldCfg.NlbParams.ded_ip_addr);
  943. ARRAYSTRCPY(pTmpIpInfo->SubnetMask, MyOldCfg.NlbParams.ded_net_mask);
  944. MyNewCfg.NumIpAddresses = 1;
  945. MyNewCfg.pIpAddressInfo = pTmpIpInfo;
  946. }
  947. }
  948. }
  949. else
  950. {
  951. if (fSetDefaults)
  952. {
  953. CfgUtilInitializeParams(&MyNewCfg.NlbParams);
  954. MyNewCfg.fValidNlbCfg = TRUE;
  955. MyNewCfg.fBound = TRUE;
  956. }
  957. else
  958. {
  959. MyNewCfg = MyOldCfg; // struct copy
  960. ASSERT(MyNewCfg.fValidNlbCfg == TRUE);
  961. ASSERT(MyNewCfg.fBound == TRUE);
  962. }
  963. //
  964. // Now Add the dedicated and cluster IPs.
  965. //
  966. ASSERT(NumIpAddresses >= 2);
  967. ARRAYSTRCPY(MyNewCfg.NlbParams.ded_ip_addr, pIpInfo[0].IpAddress);
  968. ARRAYSTRCPY(MyNewCfg.NlbParams.ded_net_mask, pIpInfo[0].SubnetMask);
  969. ARRAYSTRCPY(MyNewCfg.NlbParams.cl_ip_addr, pIpInfo[1].IpAddress);
  970. ARRAYSTRCPY(MyNewCfg.NlbParams.cl_net_mask, pIpInfo[1].SubnetMask);
  971. //
  972. // If more IPs, we explicitly add the ip list, else leave it null.
  973. //
  974. if (NumIpAddresses > 2)
  975. {
  976. MyNewCfg.pIpAddressInfo = pIpInfo;
  977. MyNewCfg.NumIpAddresses = NumIpAddresses;
  978. }
  979. else
  980. {
  981. MyNewCfg.fAddDedicatedIp = TRUE; // says to add dedicated ip.
  982. MyNewCfg.pIpAddressInfo=NULL;
  983. MyNewCfg.NumIpAddresses=0;
  984. delete pIpInfo;
  985. pIpInfo = NULL;
  986. }
  987. }
  988. display_config(szNicGuid, &MyNewCfg);
  989. printf("Going to update configuration for NIC %ws\n", szNicGuid);
  990. MyBreak(L"Break before calling DoUpdate.\n");
  991. if (szMachineName==NULL)
  992. {
  993. Status = NlbConfigurationUpdate::DoUpdate(
  994. szNicGuid,
  995. L"tprov.exe",
  996. &MyNewCfg,
  997. &Generation,
  998. &pLog
  999. );
  1000. }
  1001. else
  1002. {
  1003. Status = NlbHostDoUpdate(
  1004. &ConnInfo,
  1005. szNicGuid,
  1006. L"tprov.exe",
  1007. &MyNewCfg,
  1008. &Generation,
  1009. &pLog
  1010. );
  1011. }
  1012. if (pLog != NULL)
  1013. {
  1014. display_log(pLog);
  1015. delete pLog;
  1016. pLog = NULL;
  1017. }
  1018. if (Status == WBEM_S_PENDING)
  1019. {
  1020. printf(
  1021. "Waiting for pending operation %d...\n",
  1022. Generation
  1023. );
  1024. }
  1025. while (Status == WBEM_S_PENDING)
  1026. {
  1027. Sleep(1000);
  1028. if (szMachineName == NULL)
  1029. {
  1030. Status = NlbConfigurationUpdate::GetUpdateStatus(
  1031. szNicGuid,
  1032. Generation,
  1033. FALSE, // FALSE == Don't delete completion record
  1034. &CompletionStatus,
  1035. &pLog
  1036. );
  1037. }
  1038. else
  1039. {
  1040. Status = NlbHostGetUpdateStatus(
  1041. &ConnInfo,
  1042. szNicGuid,
  1043. Generation,
  1044. &CompletionStatus,
  1045. &pLog
  1046. );
  1047. }
  1048. if (pLog != NULL)
  1049. {
  1050. display_log(pLog);
  1051. delete pLog;
  1052. pLog = NULL;
  1053. }
  1054. if (!FAILED(Status))
  1055. {
  1056. Status = CompletionStatus;
  1057. }
  1058. }
  1059. printf(
  1060. "Final status of update %d is 0x%08lx\n",
  1061. Generation,
  1062. Status
  1063. );
  1064. }
  1065. end:
  1066. return;
  1067. }
  1068. VOID
  1069. display_ip_info(
  1070. IN UINT NumIpAddresses,
  1071. IN NLB_IP_ADDRESS_INFO *pIpInfo
  1072. )
  1073. {
  1074. UINT AddrCount = NumIpAddresses;
  1075. printf("\tNumIpAddresses=%d\n", AddrCount);
  1076. if (AddrCount != 0)
  1077. {
  1078. printf("\tAddress\t\tMask\n");
  1079. if (pIpInfo == NULL)
  1080. {
  1081. printf("ERROR: IpAddressInfo is NULL!\n");
  1082. goto end;
  1083. }
  1084. for (UINT u=0;u<AddrCount; u++)
  1085. {
  1086. printf(
  1087. "\t{%-15ws, %ws}\n",
  1088. pIpInfo[u].IpAddress,
  1089. pIpInfo[u].SubnetMask
  1090. );
  1091. }
  1092. }
  1093. end:
  1094. return;
  1095. }
  1096. VOID
  1097. display_ip_info2(
  1098. IN UINT NumIpAddresses,
  1099. IN NLB_IP_ADDRESS_INFO *pIpInfo
  1100. )
  1101. {
  1102. if (NumIpAddresses == 0)
  1103. {
  1104. wprintf(L" NetworkAddresses = {}\n");
  1105. }
  1106. else
  1107. {
  1108. wprintf(L" NetworkAddresses =\n {\n");
  1109. for (UINT u=0;u<NumIpAddresses; u++)
  1110. {
  1111. printf(
  1112. " %15ws/%ws%ws\n",
  1113. pIpInfo[u].IpAddress,
  1114. pIpInfo[u].SubnetMask,
  1115. (u==(NumIpAddresses-1)) ? L"" : L","
  1116. );
  1117. }
  1118. wprintf(L" }\n");
  1119. }
  1120. return;
  1121. }
  1122. WBEMSTATUS
  1123. read_ip_info(
  1124. IN LPCWSTR szNic,
  1125. OUT UINT *pNumIpAddresses,
  1126. OUT NLB_IP_ADDRESS_INFO **ppIpInfo
  1127. )
  1128. {
  1129. NLB_IP_ADDRESS_INFO *pIpInfo;
  1130. WBEMSTATUS Status = WBEM_NO_ERROR;
  1131. #define MAX_READ_IPS 10
  1132. printf("Enter zero or more {ip-address,subnet-mask} followed by '.'\n"
  1133. "(or 'q' to quit)\n:");
  1134. pIpInfo = new NLB_IP_ADDRESS_INFO[MAX_READ_IPS];
  1135. if (pIpInfo == NULL)
  1136. {
  1137. Status = WBEM_E_OUT_OF_MEMORY;
  1138. goto end;
  1139. }
  1140. for (UINT Index=0; Index<MAX_READ_IPS; Index++)
  1141. {
  1142. NLB_IP_ADDRESS_INFO *pInfo = pIpInfo+Index;
  1143. INT i = wscanf(
  1144. //L" { %15ws , %15ws }",
  1145. //L"{%15ws,%15ws}",
  1146. //L"{%ws,%ws}",
  1147. //L"{%[0-9.],%[0-9.]}",
  1148. L" { %15[0-9.] , %15[0-9.] }",
  1149. pInfo->IpAddress,
  1150. pInfo->SubnetMask
  1151. );
  1152. if (i!=2)
  1153. {
  1154. WCHAR Temp[100];
  1155. if ( (wscanf(L"%64ws", Temp) == 1)
  1156. && !_wcsicmp(Temp, L"q"))
  1157. {
  1158. Status = WBEM_E_OUT_OF_MEMORY;
  1159. break;
  1160. }
  1161. else if (!_wcsicmp(Temp, L"."))
  1162. {
  1163. break;
  1164. }
  1165. else if (feof(stdin))
  1166. {
  1167. Status = WBEM_E_OUT_OF_MEMORY;
  1168. break;
  1169. }
  1170. else
  1171. {
  1172. printf("Badly formed input. Try again\n");
  1173. Index--;
  1174. }
  1175. }
  1176. }
  1177. *pNumIpAddresses = Index;
  1178. end:
  1179. if (FAILED(Status))
  1180. {
  1181. if (pIpInfo != NULL)
  1182. {
  1183. delete[] pIpInfo;
  1184. pIpInfo = NULL;
  1185. }
  1186. }
  1187. *ppIpInfo = pIpInfo;
  1188. return Status;
  1189. }
  1190. VOID
  1191. do_usage(VOID)
  1192. {
  1193. wprintf(
  1194. L"\n"
  1195. L"NLBCFG host [command] [options]\n"
  1196. L"\n"
  1197. L"where\n"
  1198. L"\n"
  1199. L" \"host\" is one of\n"
  1200. L" machine name\n"
  1201. L" IP address\n"
  1202. L" fully-qualified machine name\n"
  1203. L" . (implies local machine, using WMI)\n"
  1204. L" - (implies local machine, not using WMI)\n"
  1205. L"\n"
  1206. L" \"command\" is one of\n"
  1207. L" adapterlist -- list adapters compatible with NLB\n"
  1208. L" update [adapter_guid] -- bind or update NLB configuraiton\n"
  1209. L" help|h -- display help information\n"
  1210. L"\n"
  1211. L" \"command\" may also be one of the following, used for internal testing\n"
  1212. L" ipaddr [adapter_guid] -- display and change ip addresses\n"
  1213. L" nlbbind [adapter_guid] -- bind or unbind NLB\n"
  1214. L" nlbcfg [adapter_guid] -- change NLB configuration\n"
  1215. L" \n"
  1216. L" \"options\" has the form\n"
  1217. L" /u domain\\user [password | *]\n"
  1218. L"\n"
  1219. L"List of abbreviated command names and their full forms\n"
  1220. L" al adapterlist\n"
  1221. L" u update\n"
  1222. L" ? help\n"
  1223. L"\n"
  1224. L"Examples:\n"
  1225. L"\n"
  1226. L" NLBCFG machine1 adapterlist /u:mydomain\\myname *\n"
  1227. L" Displays the list of NLB-compatible adapters on the machine with\n"
  1228. L" name \"machine1\". The \"*\" indicates that the user is to be prompted\n"
  1229. L" to enter the password.\n"
  1230. L" \n"
  1231. L"\n"
  1232. L" NLBCFG 10.0.0.1 update {AD4DA14D-CAAE-42DD-97E3-5355E55247C2}\n"
  1233. L" Binds or updates the NLB configuration on a specific adapter on\n"
  1234. L" the machine with ip address \"10.0.0.1\". The adapter is identified\n"
  1235. L" by GUID \"{AD4DA14D-CAAE-42DD-97E3-5355E55247C2}\".\n"
  1236. L"\n"
  1237. L" NLBCFG . update {AD4DA14D-CAAE-42DD-97E3-5355E55247C2}\n"
  1238. L" Binds or updates the NLB configuration on a specific adapter on\n"
  1239. L" the local machine. The adapter is identified\n"
  1240. L" by GUID \"{AD4DA14D-CAAE-42DD-97E3-5355E55247C2}\".\n"
  1241. L" \n"
  1242. L" NLBCFG .\n"
  1243. L" Opens a NLB configuration shell. This shell may be used to issue\n"
  1244. L" NLB configuration commands to the local machine.\n"
  1245. L"\n"
  1246. );
  1247. }
  1248. VOID do_niclist(
  1249. LPCWSTR szSrchFriendlyName, // OPTIONAL
  1250. LPWSTR *pszFoundGuid // OPTIONAL
  1251. )
  1252. /*
  1253. szSrchFriendlyName -- if non NULL, this function searches for a matching
  1254. GUID and returns that in pszFoundGuid (which also must be NON-NULL in this
  1255. case).
  1256. Otherwise -- this function simply prints out the adapter list.
  1257. */
  1258. {
  1259. LPWSTR *pszNics = NULL;
  1260. LPWSTR szFoundGuid = NULL;
  1261. UINT NumNics = 0;
  1262. UINT NumNlbBound = 0;
  1263. WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
  1264. BOOL fDisplay = FALSE;
  1265. BOOL fDone = FALSE;
  1266. if (szSrchFriendlyName==NULL)
  1267. {
  1268. fDisplay = TRUE;
  1269. }
  1270. else
  1271. {
  1272. fDisplay = FALSE;
  1273. *pszFoundGuid = NULL;
  1274. }
  1275. Status = CfgUtilsGetNlbCompatibleNics(&pszNics, &NumNics, &NumNlbBound);
  1276. if (FAILED(Status))
  1277. {
  1278. printf("CfgUtilsGetNlbCompatibleNics returns error 0x%08lx\n",
  1279. (UINT) Status);
  1280. pszNics = NULL;
  1281. goto end;
  1282. }
  1283. if (NumNics == 0)
  1284. {
  1285. if (fDisplay)
  1286. {
  1287. printf("No compatible local adapter guids.\n");
  1288. }
  1289. }
  1290. else
  1291. {
  1292. if (fDisplay)
  1293. {
  1294. printf("Local Adapter Guids (D==DHCP N==NLB):\n");
  1295. }
  1296. for (UINT u = 0; u<NumNics && !fDone; u++)
  1297. {
  1298. LPCWSTR szNic = pszNics[u];
  1299. LPWSTR szFriendlyName = NULL;
  1300. UINT NumIpAddresses= 0;
  1301. NLB_IP_ADDRESS_INFO *pIpInfo = NULL;
  1302. //
  1303. // Get the current list of ip addresses
  1304. //
  1305. Status = CfgUtilGetIpAddressesAndFriendlyName(
  1306. szNic,
  1307. &NumIpAddresses,
  1308. &pIpInfo,
  1309. &szFriendlyName
  1310. );
  1311. if (FAILED(Status))
  1312. {
  1313. pIpInfo = NULL;
  1314. szFriendlyName = NULL;
  1315. // wprintf(L"%ws\t<null>\t<null>\n", szNic);
  1316. wprintf(L"Error getting ip addresses for %ws\n", szNic);
  1317. }
  1318. else
  1319. {
  1320. if (fDisplay)
  1321. {
  1322. LPCWSTR szCIpAddress = L"";
  1323. LPCWSTR szCFriendlyName = L"";
  1324. LPCWSTR szNlbBound = L" ";
  1325. LPCWSTR szDHCP = L" ";
  1326. if (NumIpAddresses>0)
  1327. {
  1328. szCIpAddress = pIpInfo[0].IpAddress;
  1329. }
  1330. if (szFriendlyName != NULL)
  1331. {
  1332. szCFriendlyName = szFriendlyName;
  1333. }
  1334. //
  1335. // Get DHCP State
  1336. //
  1337. {
  1338. BOOL fDHCP = FALSE;
  1339. Status = CfgUtilGetDHCP(szNic, &fDHCP);
  1340. if (FAILED(Status))
  1341. {
  1342. printf("Error 0x%x attempting to determine DHCP state for NIC %ws",
  1343. (UINT) Status, szNic);
  1344. szDHCP = L"?";
  1345. }
  1346. else if (fDHCP)
  1347. {
  1348. szDHCP = L"D";
  1349. }
  1350. }
  1351. //
  1352. // Check if NLB bound...
  1353. //
  1354. {
  1355. BOOL fBound;
  1356. Status = CfgUtilCheckIfNlbBound(szNic, &fBound);
  1357. if (FAILED(Status))
  1358. {
  1359. fBound = FALSE;
  1360. if (Status != WBEM_E_NOT_FOUND)
  1361. {
  1362. printf("CfgUtilCheckIfNlbBound fails with error 0x%08lx\n", (UINT)Status);
  1363. szNlbBound = L"?";
  1364. }
  1365. }
  1366. if (fBound)
  1367. {
  1368. szNlbBound = L"N";
  1369. }
  1370. }
  1371. wprintf(
  1372. L"%ws %s %s %-15ws \"%ws\"\n",
  1373. szNic,
  1374. szDHCP,
  1375. szNlbBound,
  1376. szCIpAddress,
  1377. szCFriendlyName
  1378. );
  1379. }
  1380. else if (szFriendlyName != NULL)
  1381. {
  1382. if (!_wcsicmp(szSrchFriendlyName, szFriendlyName))
  1383. {
  1384. //
  1385. // Got it! Get the GUID.
  1386. //
  1387. const UINT cchLen = wcslen(szNic)+1;
  1388. szFoundGuid = new WCHAR[cchLen];
  1389. if (szFoundGuid == NULL)
  1390. {
  1391. printf("Allocation failure\n");
  1392. }
  1393. else
  1394. {
  1395. StringCchCopy(szFoundGuid, cchLen, szNic);
  1396. }
  1397. fDone = TRUE;
  1398. }
  1399. }
  1400. }
  1401. if (pIpInfo != NULL)
  1402. {
  1403. delete pIpInfo;
  1404. pIpInfo = NULL;
  1405. }
  1406. if (szFriendlyName != NULL)
  1407. {
  1408. delete szFriendlyName;
  1409. szFriendlyName = NULL;
  1410. }
  1411. }
  1412. }
  1413. end:
  1414. if (pszNics != NULL)
  1415. {
  1416. delete pszNics;
  1417. pszNics = NULL;
  1418. }
  1419. if (!fDisplay)
  1420. {
  1421. *pszFoundGuid = szFoundGuid;
  1422. }
  1423. }
  1424. VOID do_wminiclist(
  1425. LPCWSTR szSrchFriendlyName, // OPTIONAL
  1426. LPWSTR *pszFoundGuid // OPTIONAL
  1427. )
  1428. /*
  1429. szSrchFriendlyName -- if non NULL, this function searches for a matching
  1430. GUID and returns that in pszFoundGuid (which also must be NON-NULL in this
  1431. case).
  1432. Otherwise -- this function simply prints out the adapter list.
  1433. */
  1434. {
  1435. LPWSTR szMachineName = NULL;
  1436. LPWSTR *pszNics = NULL;
  1437. LPWSTR szFoundGuid = NULL;
  1438. UINT NumNics = 0;
  1439. UINT NumNlbBound = 0;
  1440. WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
  1441. BOOL fDisplay = FALSE;
  1442. BOOL fDone = FALSE;
  1443. LPWSTR szWmiMachineName = NULL;
  1444. LPWSTR szWmiMachineGuid = NULL;
  1445. BOOL fNlbMgrProviderInstalled = FALSE;
  1446. WMI_CONNECTION_INFO ConnInfo;
  1447. WMI_CONNECTION_INFO *pConnInfo = NULL;
  1448. ZeroMemory(&ConnInfo, sizeof(ConnInfo));
  1449. if (szSrchFriendlyName==NULL)
  1450. {
  1451. fDisplay = TRUE;
  1452. }
  1453. else
  1454. {
  1455. fDisplay = FALSE;
  1456. *pszFoundGuid = NULL;
  1457. }
  1458. ASSERT(g.fUseWmi);
  1459. if (!g.fLocalHost)
  1460. {
  1461. ConnInfo.szMachine = g.MachineName;
  1462. if (g.UserName[0])
  1463. {
  1464. ConnInfo.szUserName = g.UserName;
  1465. ConnInfo.szPassword = g.Password;
  1466. }
  1467. pConnInfo = &ConnInfo;
  1468. }
  1469. Status = NlbHostGetMachineIdentification(
  1470. pConnInfo,
  1471. &szWmiMachineName,
  1472. &szWmiMachineGuid,
  1473. &fNlbMgrProviderInstalled
  1474. );
  1475. if (FAILED(Status))
  1476. {
  1477. if (Status == E_ACCESSDENIED)
  1478. {
  1479. wprintf(L"Bad user name or password connecting to NLB on %ws.\n",
  1480. g.MachineName);
  1481. }
  1482. else
  1483. {
  1484. printf("NlbHostGetMachineIdentification returns error 0x%08lx\n",
  1485. (UINT) Status);
  1486. }
  1487. szWmiMachineName = NULL;
  1488. szWmiMachineGuid = NULL;
  1489. goto end;
  1490. }
  1491. if (!fNlbMgrProviderInstalled)
  1492. {
  1493. wprintf(L"NLB Manager is not installed on %ws.\n", g.MachineName);
  1494. goto end;
  1495. }
  1496. Status = NlbHostGetCompatibleNics(
  1497. pConnInfo,
  1498. &pszNics,
  1499. &NumNics,
  1500. &NumNlbBound
  1501. );
  1502. if (FAILED(Status))
  1503. {
  1504. if (Status == E_ACCESSDENIED)
  1505. {
  1506. wprintf(L"Bad user name or password connecting to NLB on %ws.\n",
  1507. g.MachineName);
  1508. }
  1509. else
  1510. {
  1511. printf("NlbHostGetNlbCompatibleNics returns error 0x%08lx\n",
  1512. (UINT) Status);
  1513. }
  1514. pszNics = NULL;
  1515. goto end;
  1516. }
  1517. if (NumNics == 0 && fDisplay)
  1518. {
  1519. printf("No compatible local adapter guids.\n");
  1520. }
  1521. else
  1522. {
  1523. BOOL fSavedSilent = g_Silent;
  1524. g_Silent = TRUE;
  1525. if (fDisplay)
  1526. {
  1527. if (szWmiMachineName != NULL)
  1528. {
  1529. printf("Machine Name: %ws\n", szWmiMachineName);
  1530. }
  1531. if (szWmiMachineGuid != NULL)
  1532. {
  1533. printf("Machine GUID: %ws\n", szWmiMachineGuid);
  1534. }
  1535. printf("Local Adapter Guids (D==DHCP N==NLB):\n", NumNlbBound);
  1536. }
  1537. for (UINT u=0; u<NumNics && !fDone; u++)
  1538. {
  1539. NLB_EXTENDED_CLUSTER_CONFIGURATION NlbCfg; // class
  1540. LPCWSTR szNic = pszNics[u];
  1541. Status = NlbHostGetConfiguration(
  1542. pConnInfo,
  1543. szNic,
  1544. &NlbCfg
  1545. );
  1546. if (FAILED(Status))
  1547. {
  1548. // wprintf(L"%ws\t<null>\t<null>\n", szNic);
  1549. wprintf(L"Error reading extended configuration for %ws\n", szNic);
  1550. }
  1551. else
  1552. {
  1553. UINT NumIpAddresses= 0;
  1554. NLB_IP_ADDRESS_INFO *pIpInfo = NULL;
  1555. LPWSTR szFriendlyName = NULL;
  1556. LPCWSTR szCIpAddress = L"";
  1557. LPCWSTR szCFriendlyName = L"";
  1558. LPWSTR *pszNetworkAddresses = NULL;
  1559. LPCWSTR szNlbBound = L" ";
  1560. LPCWSTR szDHCP = L" ";
  1561. if (fDisplay)
  1562. {
  1563. Status = NlbCfg.GetNetworkAddresses(
  1564. &pszNetworkAddresses,
  1565. &NumIpAddresses
  1566. );
  1567. if (FAILED(Status))
  1568. {
  1569. wprintf(L"Error extracting IP addresses for %ws\n", szNic);
  1570. NumIpAddresses = 0;
  1571. pszNetworkAddresses = NULL;
  1572. }
  1573. if (NumIpAddresses>0)
  1574. {
  1575. szCIpAddress = pszNetworkAddresses[0];
  1576. //
  1577. // NetworkAddresses are of the form "10.0.0.1/255.255.255.0"
  1578. // So we truncate this by putting a '\0' where the '/' is.
  1579. //
  1580. {
  1581. LPWSTR pSlash = wcsrchr(szCIpAddress, (int) '/');
  1582. if (pSlash != NULL)
  1583. {
  1584. *pSlash = 0;
  1585. }
  1586. }
  1587. }
  1588. if (NlbCfg.IsNlbBound())
  1589. {
  1590. szNlbBound = L"N";
  1591. }
  1592. if (NlbCfg.fDHCP)
  1593. {
  1594. szNlbBound = L"D";
  1595. }
  1596. }
  1597. Status = NlbCfg.GetFriendlyName(
  1598. &szFriendlyName
  1599. );
  1600. if (FAILED(Status))
  1601. {
  1602. szFriendlyName = NULL;
  1603. }
  1604. if (fDisplay)
  1605. {
  1606. if (szFriendlyName != NULL)
  1607. {
  1608. szCFriendlyName = szFriendlyName;
  1609. }
  1610. wprintf(
  1611. L"%ws %ws %ws %-15ws \"%ws\"\n",
  1612. szNic,
  1613. szDHCP,
  1614. szNlbBound,
  1615. szCIpAddress,
  1616. szCFriendlyName
  1617. );
  1618. }
  1619. else if (szFriendlyName != NULL)
  1620. {
  1621. if (!_wcsicmp(szSrchFriendlyName, szFriendlyName))
  1622. {
  1623. //
  1624. // Got it! Get the GUID.
  1625. //
  1626. const UINT cchLen = wcslen(szNic)+1;
  1627. szFoundGuid = new WCHAR[cchLen];
  1628. if (szFoundGuid == NULL)
  1629. {
  1630. printf("Allocation failure\n");
  1631. }
  1632. else
  1633. {
  1634. StringCchCopy(szFoundGuid, cchLen, szNic);
  1635. }
  1636. fDone = TRUE;
  1637. }
  1638. }
  1639. if (szFriendlyName != NULL)
  1640. {
  1641. delete szFriendlyName;
  1642. szFriendlyName = NULL;
  1643. }
  1644. if (pszNetworkAddresses != NULL)
  1645. {
  1646. delete pszNetworkAddresses;
  1647. pszNetworkAddresses = NULL;
  1648. }
  1649. }
  1650. }
  1651. g_Silent = fSavedSilent;
  1652. }
  1653. end:
  1654. delete szMachineName;
  1655. delete pszNics;
  1656. delete szWmiMachineName;
  1657. delete szWmiMachineGuid;
  1658. if (!fDisplay)
  1659. {
  1660. *pszFoundGuid = szFoundGuid;
  1661. }
  1662. }
  1663. VOID do_ipaddr(VOID)
  1664. {
  1665. LPWSTR szNic = NULL;
  1666. //
  1667. // Skip reading the GUID if we've got it from the command line.
  1668. //
  1669. if (!g.fGotGuid)
  1670. {
  1671. if (!read_guid(&szNic)) goto end;
  1672. ARRAYSTRCPY(g.AdapterGuid, szNic);
  1673. }
  1674. test_add_ips(szNic);
  1675. end:
  1676. if (szNic!=NULL)
  1677. {
  1678. delete szNic;
  1679. }
  1680. }
  1681. VOID do_nlbcfg(VOID)
  1682. {
  1683. LPWSTR szNic = NULL;
  1684. //
  1685. // Skip reading the GUID if we've got it from the command line.
  1686. //
  1687. if (!g.fGotGuid)
  1688. {
  1689. if (!read_guid(&szNic)) goto end;
  1690. ARRAYSTRCPY(g.AdapterGuid, szNic);
  1691. }
  1692. test_cfg_nlb(szNic);
  1693. end:
  1694. if (szNic!=NULL)
  1695. {
  1696. delete szNic;
  1697. }
  1698. }
  1699. VOID do_nlbbind(VOID)
  1700. {
  1701. LPWSTR szNic = NULL;
  1702. //
  1703. // Skip reading the GUID if we've got it from the command line.
  1704. //
  1705. if (!g.fGotGuid)
  1706. {
  1707. if (!read_guid(&szNic)) goto end;
  1708. ARRAYSTRCPY(g.AdapterGuid, szNic);
  1709. }
  1710. test_bind_nlb(szNic);
  1711. end:
  1712. if (szNic!=NULL)
  1713. {
  1714. delete szNic;
  1715. }
  1716. }
  1717. VOID do_update(VOID)
  1718. {
  1719. LPWSTR szNic = NULL;
  1720. if (!read_guid(&szNic))
  1721. {
  1722. szNic = NULL;
  1723. goto end;
  1724. }
  1725. test_update(NULL, szNic); // NULL == don't use WMI
  1726. end:
  1727. if (szNic!=NULL)
  1728. {
  1729. delete szNic;
  1730. }
  1731. }
  1732. VOID do_wmiupdate(VOID)
  1733. {
  1734. LPWSTR szNic = NULL;
  1735. LPWSTR szMachineName = NULL;
  1736. if (!read_machinename(&szMachineName))
  1737. {
  1738. szMachineName = NULL;
  1739. goto end;
  1740. }
  1741. if (!read_guid(&szNic))
  1742. {
  1743. szNic = NULL;
  1744. goto end;
  1745. }
  1746. test_update(szMachineName, szNic); // TRUE == use WMI
  1747. end:
  1748. if (szNic!=NULL)
  1749. {
  1750. delete szNic;
  1751. }
  1752. if (szMachineName!=NULL)
  1753. {
  1754. delete szMachineName;
  1755. }
  1756. }
  1757. VOID do_cleanreg(VOID)
  1758. {
  1759. printf("Unimplemented\n");
  1760. }
  1761. BOOL read_guid(
  1762. LPWSTR *pszNic
  1763. )
  1764. {
  1765. BOOL fRet = FALSE;
  1766. BOOL fValid = FALSE;
  1767. LPWSTR szNic = NULL;
  1768. #if 1
  1769. WCHAR rgTemp[256];
  1770. printf("Enter Adapter GUID: ");
  1771. do
  1772. {
  1773. // if (wscanf(L" %40[-{}a-fA-F0-9]", rgTemp)==1)
  1774. if (wscanf(L" %200ws", rgTemp) == 1)
  1775. {
  1776. fValid = valid_guid(rgTemp);
  1777. }
  1778. if (!fValid)
  1779. {
  1780. if (feof(stdin)) goto end;
  1781. printf("Incorrect format. Please re-enter Adapter Guid: ");
  1782. }
  1783. } while (!fValid);
  1784. #else
  1785. LPCWSTR rgTemp = L"{AD4DA14D-CAAE-42DD-97E3-5355E55247C2}";
  1786. #endif // 0
  1787. const UINT cchLen = wcslen(rgTemp)+1;
  1788. szNic = new WCHAR[cchLen];
  1789. if (szNic != NULL)
  1790. {
  1791. StringCchCopy(szNic, cchLen, rgTemp);
  1792. fRet = TRUE;
  1793. }
  1794. end:
  1795. *pszNic = szNic;
  1796. return fRet;
  1797. }
  1798. BOOL read_machinename(
  1799. LPWSTR *pszMachineName
  1800. )
  1801. {
  1802. BOOL fRet = FALSE;
  1803. #if 0
  1804. WCHAR rgTemp[256];
  1805. printf("\nEnter Machine Name (or '.' for local)\n:");
  1806. while (wscanf(L" %[a-zA-Z0-9._-]", rgTemp)!=1)
  1807. {
  1808. wscanf(L" %200s", rgTemp);
  1809. printf("Incorrect format. Please try again.\n");
  1810. }
  1811. if (!wcscmp(rgTemp, L"."))
  1812. {
  1813. // convert "." to ""
  1814. *rgTemp=0;
  1815. }
  1816. #else
  1817. // LPCWSTR rgTemp = L"JOSEPHJ4E";
  1818. LPCWSTR rgTemp = L"";
  1819. #endif
  1820. const UINT cchLen = wcslen(rgTemp)+1;
  1821. LPWSTR szMachineName = new WCHAR[cchLen];
  1822. if (szMachineName != NULL)
  1823. {
  1824. StringCchCopy(szMachineName, cchLen, rgTemp);
  1825. fRet = TRUE;
  1826. }
  1827. *pszMachineName = szMachineName;
  1828. return fRet;
  1829. }
  1830. void test_safearray(void)
  1831. {
  1832. SAFEARRAY *pSA;
  1833. LPCWSTR pInStrings[] =
  1834. {
  1835. L"String1",
  1836. #if 1
  1837. L"String2",
  1838. L"String3",
  1839. #endif // 0
  1840. NULL // must be last.
  1841. };
  1842. LPWSTR *pOutStrings=NULL;
  1843. UINT NumInStrings=0;
  1844. UINT NumOutStrings=0;
  1845. WBEMSTATUS Status;
  1846. //
  1847. // Find count of strings...
  1848. //
  1849. for (NumInStrings=0; pInStrings[NumInStrings]!=NULL; NumInStrings++)
  1850. {
  1851. ;
  1852. }
  1853. Status = CfgUtilSafeArrayFromStrings(
  1854. pInStrings,
  1855. NumInStrings,
  1856. &pSA
  1857. );
  1858. if (FAILED(Status))
  1859. {
  1860. printf("CfgUtilSafeArrayFromStrings failed with error 0x%08lx\n", (UINT)Status);
  1861. pSA = NULL;
  1862. goto end;
  1863. }
  1864. Status = CfgUtilStringsFromSafeArray(
  1865. pSA,
  1866. &pOutStrings,
  1867. &NumOutStrings
  1868. );
  1869. if (FAILED(Status))
  1870. {
  1871. printf("CfgUtilStringsFromSafeArray failed with error 0x%08lx\n", (UINT)Status);
  1872. pOutStrings = NULL;
  1873. goto end;
  1874. }
  1875. //
  1876. // Check that they match
  1877. //
  1878. if (NumOutStrings != NumInStrings)
  1879. {
  1880. printf("ERROR: NumOutStrings != NumInStrings.\n");
  1881. goto end;
  1882. }
  1883. for (UINT u=0; u < NumInStrings; u++)
  1884. {
  1885. if (wcscmp(pInStrings[u], pOutStrings[u]))
  1886. {
  1887. printf("MISMATCH: %ws->%ws\n", pInStrings[u], pOutStrings[u]);
  1888. }
  1889. else
  1890. {
  1891. printf("MATCH: %ws->%ws\n", pInStrings[u], pOutStrings[u]);
  1892. }
  1893. }
  1894. end:
  1895. if (pSA!=NULL)
  1896. {
  1897. SafeArrayDestroy(pSA);
  1898. pSA = NULL;
  1899. }
  1900. if (pOutStrings!=NULL)
  1901. {
  1902. delete pOutStrings;
  1903. pOutStrings = NULL;
  1904. }
  1905. return;
  1906. }
  1907. VOID test_exfcfgclass(void)
  1908. /*
  1909. tests some of the methods of class NLB_EXTENDED_CLUSTER_CONFIGURATION
  1910. 1. Initialize Cfg
  1911. 2. Set a bunch of fields
  1912. 3. display Cfg
  1913. 4. Get and set a bunch of fields on new
  1914. 5. display cfg
  1915. */
  1916. {
  1917. typedef enum
  1918. {
  1919. DO_STRINGS,
  1920. DO_SAFEARRAY,
  1921. DO_STRINGPAIR,
  1922. DO_END
  1923. } TEST_COMMAND;
  1924. TEST_COMMAND cmd;
  1925. printf("Test of NLB_EXTENDED_CLUSTER_CONFIGURATION methods...\n");
  1926. UINT u1=100000L;
  1927. // while(u1--> 0)
  1928. {
  1929. // g_Silent = TRUE;
  1930. for (cmd=DO_STRINGS; cmd<DO_END; cmd=(TEST_COMMAND)((UINT)cmd + 1))
  1931. {
  1932. NLB_EXTENDED_CLUSTER_CONFIGURATION Cfg;
  1933. NLB_EXTENDED_CLUSTER_CONFIGURATION NewCfg;
  1934. WBEMSTATUS Status = WBEM_NO_ERROR;
  1935. CfgUtilInitializeParams(&Cfg.NlbParams);
  1936. CfgUtilInitializeParams(&NewCfg.NlbParams);
  1937. //
  1938. // Set a bunch of fields in Cfg
  1939. //
  1940. {
  1941. #define TPROV_NUM_ADDRESSES 2
  1942. #define TPROV_NUM_PORTS 1
  1943. LPCWSTR rgszNetworkAddresses[TPROV_NUM_ADDRESSES] = {
  1944. L"10.0.0.1/255.0.0.0",
  1945. L"10.0.0.2/255.0.0.0"
  1946. };
  1947. LPCWSTR rgszIpAddresses[TPROV_NUM_ADDRESSES] = {
  1948. L"10.0.0.1",
  1949. L"10.0.0.2"
  1950. };
  1951. LPCWSTR rgszSubnetMasks[TPROV_NUM_ADDRESSES] = {
  1952. L"255.255.255.0",
  1953. L"255.255.0.0"
  1954. };
  1955. LPCWSTR rgszPortRules[TPROV_NUM_PORTS] = {
  1956. L"ip=1.1.1.1 protocol=TCP start=80 end=288 mode=SINGLE priority=1"
  1957. };
  1958. UINT NumOldNetworkAddresses = TPROV_NUM_ADDRESSES;
  1959. UINT NumOldPortRules=TPROV_NUM_PORTS;
  1960. Cfg.fValidNlbCfg = TRUE;
  1961. Cfg.Generation = 123;
  1962. Cfg.fBound = TRUE;
  1963. if (cmd == DO_STRINGS)
  1964. {
  1965. Status = Cfg.SetNetworkAddresses(
  1966. rgszNetworkAddresses,
  1967. NumOldNetworkAddresses
  1968. );
  1969. }
  1970. else if (cmd == DO_SAFEARRAY)
  1971. {
  1972. SAFEARRAY *pOldSA = NULL;
  1973. Status = CfgUtilSafeArrayFromStrings(
  1974. rgszNetworkAddresses,
  1975. NumOldNetworkAddresses,
  1976. &pOldSA
  1977. );
  1978. if (FAILED(Status))
  1979. {
  1980. printf("ERROR: couldn't create safe array!\n");
  1981. pOldSA = NULL;
  1982. }
  1983. if (pOldSA != NULL)
  1984. {
  1985. Status = Cfg.SetNetworkAddressesSafeArray(pOldSA);
  1986. SafeArrayDestroy(pOldSA);
  1987. pOldSA = NULL;
  1988. }
  1989. }
  1990. else if (cmd == DO_STRINGPAIR)
  1991. {
  1992. Status = Cfg.SetNetworkAddresPairs(
  1993. rgszIpAddresses,
  1994. rgszSubnetMasks,
  1995. NumOldNetworkAddresses
  1996. );
  1997. }
  1998. Status = Cfg.SetPortRules(rgszPortRules, NumOldPortRules);
  1999. Cfg.SetClusterNetworkAddress(L"10.0.0.11/255.0.0.0");
  2000. Cfg.SetDedicatedNetworkAddress(L"10.0.0.1/255.0.0.0");
  2001. Cfg.SetTrafficMode(
  2002. NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_UNICAST
  2003. );
  2004. Cfg.SetHostPriority(10);
  2005. Cfg.SetClusterModeOnStart( CVY_HOST_STATE_STOPPED );
  2006. Cfg.SetPersistSuspendOnReboot( FALSE );
  2007. Cfg.SetRemoteControlEnabled(TRUE);
  2008. Cfg.fValidNlbCfg = TRUE;
  2009. }
  2010. display_config2(L"<dummy nic:old>", &Cfg);
  2011. //
  2012. // Get all the fields and push it into NewCfg;
  2013. //
  2014. {
  2015. UINT NumNetworkAddresses = 0;
  2016. UINT NumPortRules=0;
  2017. LPWSTR *pszNetworkAddresses=NULL;
  2018. LPWSTR *pszIpAddresses=NULL;
  2019. LPWSTR *pszSubnetMasks=NULL;
  2020. LPWSTR *pszPortRules=NULL;
  2021. LPWSTR szClusterAddress = NULL;
  2022. LPWSTR szDedicatedAddress = NULL;
  2023. UINT Generation=0;
  2024. BOOL NlbBound=FALSE;
  2025. BOOL ValidNlbConfig=FALSE;
  2026. SAFEARRAY *pSA = NULL;
  2027. NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE
  2028. TrafficMode=NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_UNICAST;
  2029. /*
  2030. NLB_EXTENDED_CLUSTER_CONFIGURATION::START_MODE
  2031. StartMode=NLB_EXTENDED_CLUSTER_CONFIGURATION::START_MODE_STOPPED;
  2032. */
  2033. DWORD StartMode = CVY_HOST_STATE_STOPPED;
  2034. BOOL PersistSuspendOnReboot = FALSE;
  2035. UINT HostPriority=0;
  2036. BOOL RemoteControlEnabled=FALSE;
  2037. //
  2038. // GET
  2039. //
  2040. Generation = Cfg.GetGeneration();
  2041. NlbBound = Cfg.IsNlbBound();
  2042. ValidNlbConfig = Cfg.IsValidNlbConfig();
  2043. if (cmd == DO_STRINGS)
  2044. {
  2045. Status = Cfg.GetNetworkAddresses(
  2046. &pszNetworkAddresses,
  2047. &NumNetworkAddresses
  2048. );
  2049. }
  2050. else if (cmd == DO_SAFEARRAY)
  2051. {
  2052. Status = Cfg.GetNetworkAddressesSafeArray(&pSA);
  2053. if (FAILED(Status))
  2054. {
  2055. pSA = NULL;
  2056. }
  2057. }
  2058. else if (cmd == DO_STRINGPAIR)
  2059. {
  2060. Status = Cfg.GetNetworkAddressPairs(
  2061. &pszIpAddresses, // free using delete
  2062. &pszSubnetMasks, // free using delete
  2063. &NumNetworkAddresses
  2064. );
  2065. }
  2066. Status = Cfg.GetPortRules(&pszPortRules, &NumPortRules);
  2067. Status = Cfg.GetClusterNetworkAddress(&szClusterAddress);
  2068. Status = Cfg.GetDedicatedNetworkAddress(&szDedicatedAddress);
  2069. TrafficMode = Cfg.GetTrafficMode();
  2070. HostPriority = Cfg.GetHostPriority();
  2071. StartMode = Cfg.GetClusterModeOnStart();
  2072. PersistSuspendOnReboot = Cfg.GetPersistSuspendOnReboot();
  2073. RemoteControlEnabled = Cfg.GetRemoteControlEnabled();
  2074. //
  2075. // SET
  2076. //
  2077. NewCfg.fValidNlbCfg = ValidNlbConfig;
  2078. NewCfg.Generation = Generation;
  2079. NewCfg.fBound = NlbBound;
  2080. if (cmd == DO_STRINGS)
  2081. {
  2082. Status = NewCfg.SetNetworkAddresses(
  2083. (LPCWSTR*) pszNetworkAddresses,
  2084. NumNetworkAddresses
  2085. );
  2086. }
  2087. else if (cmd == DO_SAFEARRAY)
  2088. {
  2089. if (pSA != NULL)
  2090. {
  2091. Status = NewCfg.SetNetworkAddressesSafeArray(pSA);
  2092. SafeArrayDestroy(pSA);
  2093. pSA = NULL;
  2094. }
  2095. }
  2096. else if (cmd == DO_STRINGPAIR)
  2097. {
  2098. Status = NewCfg.SetNetworkAddresPairs(
  2099. (LPCWSTR*) pszIpAddresses,
  2100. (LPCWSTR*) pszSubnetMasks,
  2101. NumNetworkAddresses
  2102. );
  2103. }
  2104. Status = NewCfg.SetPortRules((LPCWSTR*)pszPortRules, NumPortRules);
  2105. NewCfg.SetClusterNetworkAddress(szClusterAddress);
  2106. NewCfg.SetDedicatedNetworkAddress(szDedicatedAddress);
  2107. NewCfg.SetTrafficMode(TrafficMode);
  2108. NewCfg.SetHostPriority(HostPriority);
  2109. NewCfg.SetClusterModeOnStart(StartMode);
  2110. NewCfg.SetPersistSuspendOnReboot(PersistSuspendOnReboot);
  2111. NewCfg.SetRemoteControlEnabled(RemoteControlEnabled);
  2112. delete (pszNetworkAddresses);
  2113. delete (pszIpAddresses);
  2114. delete (pszSubnetMasks);
  2115. delete (pszPortRules);
  2116. delete (szClusterAddress);
  2117. delete (szDedicatedAddress);
  2118. }
  2119. display_config2(L"<dummy nic:new>", &NewCfg);
  2120. }
  2121. }
  2122. printf("... end test\n");
  2123. }
  2124. #if 0
  2125. AdapterList al
  2126. Update u
  2127. Quit q
  2128. Help h, ?
  2129. AdapterGuid ag
  2130. PartialUpdate pu
  2131. NetworkAddresses na
  2132. NLBBound nb
  2133. ClusterNetworkAddress cna
  2134. ClusterName cn
  2135. TrafficMode tm
  2136. PortRules pr
  2137. HostPriority hp
  2138. DedicatedNetworkAddress dna
  2139. ClusterModeOnStart cmos
  2140. RemoteControlEnabled rce
  2141. Password p
  2142. .
  2143. #endif // 0
  2144. BOOL read_password(
  2145. VOID
  2146. )
  2147. {
  2148. BOOL fRet = TRUE;
  2149. DWORD dwLen = 0;
  2150. wprintf(L"Type the password for %ws: ", g.MachineName);
  2151. fRet = GetPassword(g.Password, ARRAY_LENGTH(g.Password)-1, &dwLen);
  2152. if (!fRet)
  2153. {
  2154. printf("Error getting password!\n");
  2155. g.Password[0] = 0;
  2156. }
  2157. return fRet;
  2158. }
  2159. KEYWORD
  2160. parse_args(int argc, WCHAR* argv[])
  2161. /*++
  2162. // tprov [niclist|ipaddr|nlbcfg|nlbbind]
  2163. nlbcfg machinename|-|. [command_and_parameters] [options]
  2164. machinemame machine name
  2165. OR IP address
  2166. OR fully-qualified machine name
  2167. - Indicates not to use WMI -- call lower-level functions
  2168. directly
  2169. . Connect to local machine using wmi
  2170. command_and_parameters AdapterList
  2171. OR Update [adapter_guid]
  2172. OR Help
  2173. OR ipaddr [adapter_guid] (test)
  2174. OR nlbbinb [adapter_guid] (test)
  2175. OR nlbcfg [adapter_guid] (test)
  2176. options /u domain\user [password | *]
  2177. --*/
  2178. {
  2179. KEYWORD kw = KW_UNKNOWN;
  2180. //
  2181. // If no args, or one arg and that is /? or /help, we display help.
  2182. //
  2183. {
  2184. BOOL fDoHelp = FALSE;
  2185. if (argc<2)
  2186. {
  2187. fDoHelp = TRUE;
  2188. }
  2189. else if (argc == 2)
  2190. {
  2191. if (!_wcsicmp(argv[1], L"/?") || !wcscmp(argv[1], L"/help"))
  2192. {
  2193. fDoHelp = TRUE;
  2194. }
  2195. }
  2196. if (fDoHelp)
  2197. {
  2198. kw = KW_HELP;
  2199. goto end;
  2200. }
  2201. }
  2202. argv++; // skip past program name.
  2203. argc--;
  2204. g.fReadPassword = FALSE;
  2205. g.fGotGuid = FALSE;
  2206. g.fGotFriendlyName = FALSE;
  2207. g.fRunOnce = FALSE;
  2208. g.fUseWmi = FALSE;
  2209. g.fLocalHost = FALSE;
  2210. g.MachineName[0] = 0;
  2211. g.UserName[0] = 0;
  2212. g.Password[0] = 0;
  2213. #if 0
  2214. #define MAX_MACHINE_NAME_LENGTH 256
  2215. #define MAX_PASSWORD_LENGTH 256
  2216. #define INPUT_BUFFER_LENGTH 256
  2217. WCHAR MachineName[MAX_MACHINE_NAME_LENGTH+1];
  2218. WCHAR Password[MAX_PASSWORD_LENGTH+1];
  2219. WCHAR InputBuffer[INPUT_BUFFER_LENGTH+1];
  2220. BOOL fUseWmi;
  2221. BOOL fLocalHost;
  2222. #endif // 0
  2223. //
  2224. // Get the mandatory machine name information, which must be first.
  2225. //
  2226. {
  2227. if (!_wcsicmp(*argv, L"-"))
  2228. {
  2229. g.fUseWmi = FALSE;
  2230. }
  2231. else if (!wcscmp(*argv, L"."))
  2232. {
  2233. g.fUseWmi = TRUE;
  2234. g.fLocalHost = TRUE;
  2235. }
  2236. else
  2237. {
  2238. //
  2239. // read machine name
  2240. //
  2241. if (wcslen(*argv) >= ARRAY_LENGTH(g.MachineName))
  2242. {
  2243. wprintf(L"Machine name should be a maximum of %lu characters.\n",
  2244. ARRAY_LENGTH(g.MachineName)-1);
  2245. goto end;
  2246. }
  2247. ARRAYSTRCPY(g.MachineName, *argv);
  2248. g.fUseWmi = TRUE;
  2249. }
  2250. argv++;
  2251. argc--;
  2252. }
  2253. while (argc)
  2254. {
  2255. if (!_wcsnicmp(*argv, L"/u:", 3))
  2256. {
  2257. //
  2258. // Parse user name and password
  2259. //
  2260. LPCWSTR szUser = (*argv)+3;
  2261. wprintf(L"OPTION USER -- User==\"%ws\"\n", szUser);
  2262. UINT Len = wcslen(szUser);
  2263. if (Len == 0 || Len >= ARRAY_LENGTH(g.UserName))
  2264. {
  2265. wprintf(L"Invalid User Name: \"%ws\"\n", szUser);
  2266. goto end;
  2267. }
  2268. ARRAYSTRCPY(g.UserName, szUser);
  2269. argv++;
  2270. argc--;
  2271. if (argc)
  2272. {
  2273. //
  2274. // Get the password
  2275. //
  2276. LPCWSTR szPassword = *argv;
  2277. wprintf(L"PASSWORD=\"%ws\"\n", szPassword);
  2278. Len = wcslen(szUser);
  2279. if (Len >= ARRAY_LENGTH(g.Password))
  2280. {
  2281. wprintf(L"Pasword too long\n");
  2282. goto end;
  2283. }
  2284. if (!wcscmp(szPassword, L"*"))
  2285. {
  2286. g.fReadPassword = TRUE;
  2287. }
  2288. else
  2289. {
  2290. g.fReadPassword = FALSE;
  2291. ARRAYSTRCPY(g.Password, szPassword);
  2292. }
  2293. argv++;
  2294. argc--;
  2295. }
  2296. }
  2297. else
  2298. {
  2299. BOOL fNeedGuid = FALSE;
  2300. if (g.fRunOnce)
  2301. {
  2302. //
  2303. // We've already picked up a command to execute,
  2304. // so this is unexpected.
  2305. //
  2306. wprintf(L"Unexpected parameter \"%ws\"\n", *argv);
  2307. kw = KW_UNKNOWN;
  2308. goto end;
  2309. }
  2310. g.fRunOnce = TRUE;
  2311. kw = lookup_keyword(*argv);
  2312. switch(kw)
  2313. {
  2314. case KW_UPDATE:
  2315. case KW_IPADDR:
  2316. case KW_NLBBIND:
  2317. case KW_NLBCFG:
  2318. fNeedGuid = TRUE;
  2319. break;
  2320. case KW_ADAPTER_LIST:
  2321. case KW_HELP:
  2322. break;
  2323. default:
  2324. wprintf(L"Unexpected parameter \"%ws\"\n", *argv);
  2325. kw = KW_UNKNOWN;
  2326. goto end;
  2327. }
  2328. argv++;
  2329. argc--;
  2330. if (fNeedGuid)
  2331. {
  2332. g.fGotGuid = FALSE;
  2333. g.fGotFriendlyName = FALSE;
  2334. if (argc)
  2335. {
  2336. LPCWSTR szGuid = *argv;
  2337. //
  2338. // Get the NIC GUID or friendly name
  2339. //
  2340. UINT Len = wcslen(szGuid);
  2341. if (!Len)
  2342. {
  2343. argv++;
  2344. argc--;
  2345. continue;
  2346. }
  2347. if (
  2348. Len==NLB_GUID_LEN
  2349. && szGuid[0] == '{'
  2350. && szGuid[Len-1]=='}'
  2351. )
  2352. {
  2353. ARRAYSTRCPY(g.AdapterGuid, szGuid);
  2354. g.fGotGuid = TRUE;
  2355. argv++;
  2356. argc--;
  2357. }
  2358. else if (szGuid[0] == '/')
  2359. {
  2360. // Treat this as an option, not friendly name.
  2361. }
  2362. else if ( szGuid[0] != '{' // '}'
  2363. && Len < NLB_MAX_FRIENDLY_NAME_LENGTH)
  2364. {
  2365. //
  2366. // let's assume that this is a friendly name
  2367. //
  2368. // Note -- I checked and friendly name can be
  2369. // pretty much any printible character -- including
  2370. // ! etc.
  2371. //
  2372. // SO "/....." is a valid friendly name, but we
  2373. // treat it like an option.
  2374. // Also, "{....}" is a valid friendly name, but we
  2375. // assume it's a malformed guid.
  2376. //
  2377. ARRAYSTRCPY(g.FriendlyName, szGuid);
  2378. g.fGotFriendlyName = TRUE;
  2379. argv++;
  2380. argc--;
  2381. }
  2382. else
  2383. {
  2384. wprintf(L"Expecting Adapter GUID or frienly name, not \"%ws\"\n", szGuid);
  2385. kw = KW_UNKNOWN;
  2386. goto end;
  2387. }
  2388. }
  2389. }
  2390. }
  2391. }
  2392. if (kw==KW_UNKNOWN)
  2393. {
  2394. //
  2395. // This means that no command was specified -- we invoke the
  2396. // shell
  2397. //
  2398. kw = KW_MAIN_SHELL;
  2399. }
  2400. #if 0
  2401. if (!wcscmp(argv[1], L"/uipaddr"))
  2402. if (!wcscmp(argv[1], L"ipaddr"))
  2403. {
  2404. ret = DO_IPADDR;
  2405. }
  2406. else if (!wcscmp(argv[1], L"nlbcfg"))
  2407. {
  2408. ret = DO_NLBCFG;
  2409. }
  2410. else if (!wcscmp(argv[1], L"nlbbind"))
  2411. {
  2412. ret = DO_NLBBIND;
  2413. }
  2414. else if (!wcscmp(argv[1], L"update"))
  2415. {
  2416. ret = DO_UPDATE;
  2417. }
  2418. else if (!wcscmp(argv[1], L"wmiupdate"))
  2419. {
  2420. ret = DO_WMIUPDATE;
  2421. }
  2422. else if (!wcscmp(argv[1], L"cleanreg"))
  2423. {
  2424. ret = DO_CLEANREG;
  2425. }
  2426. else
  2427. {
  2428. printf("ERROR: unknown argument\n");
  2429. }
  2430. #endif // 0
  2431. end:
  2432. return kw;
  2433. }
  2434. KEYWORD lookup_keyword(LPCWSTR szKeyword)
  2435. {
  2436. KEYWORD kw = KW_UNKNOWN;
  2437. const KEYWORD_MAP *pMap = KeywordMap;
  2438. for (; pMap->sz!=NULL; pMap++)
  2439. {
  2440. if (!_wcsicmp(szKeyword, pMap->sz))
  2441. {
  2442. // printf("Matched %ws. kw=%lu\n", pMap->sz, pMap->kw);
  2443. break;
  2444. }
  2445. }
  2446. if (pMap->sz != NULL)
  2447. {
  2448. kw = pMap->kw;
  2449. }
  2450. return kw;
  2451. }
  2452. KEYWORD read_keyword(LPCWSTR szPrompt)
  2453. /*++
  2454. If global (g.fRunOnce) is TRUE, return immediately with KW_QUIT.
  2455. Otherwise, read and identify a keyword from a set of pre-defined keywords.
  2456. --*/
  2457. {
  2458. KEYWORD kw = KW_UNKNOWN;
  2459. g.InputBuffer[0] = 0;
  2460. wprintf(L"%s", szPrompt);
  2461. //
  2462. // Skip past comment characters...
  2463. //
  2464. while (wscanf(L" %1[;]", g.InputBuffer) == 1)
  2465. {
  2466. // skip rest of this line...
  2467. WCHAR wc = 0;
  2468. do {
  2469. wc = getwchar();
  2470. } while (wc != WEOF && wc != '\n' && wc != '\r');
  2471. }
  2472. if (wscanf(L" %50[a-zA-Z.?]", g.InputBuffer) != 1)
  2473. {
  2474. //
  2475. // Invalid input, lets try to read it all into our buffer
  2476. //
  2477. if (wscanf(L"%100ws", g.InputBuffer) == 1)
  2478. {
  2479. g.InputBuffer[0] = 0;
  2480. }
  2481. goto end;
  2482. }
  2483. kw = lookup_keyword(g.InputBuffer);
  2484. end:
  2485. if (kw == KW_UNKNOWN)
  2486. {
  2487. if (feof(stdin))
  2488. {
  2489. kw = KW_QUIT;
  2490. }
  2491. else
  2492. {
  2493. //
  2494. // Kill all subsequent input
  2495. //
  2496. fseek(stdin, 0, SEEK_END);
  2497. }
  2498. }
  2499. return kw;
  2500. }
  2501. void
  2502. test_read_keyword(void)
  2503. {
  2504. KEYWORD kw;
  2505. do
  2506. {
  2507. kw = read_keyword(L"test: ");
  2508. } while (kw != KW_QUIT);
  2509. }
  2510. void parse_main(int argc, WCHAR* argv[])
  2511. {
  2512. #define szMAIN_PROMPT L"nlbcfg: "
  2513. KEYWORD kw;
  2514. kw = parse_args(argc, argv);
  2515. #if 0
  2516. wprintf(L"ARGS: MachineName = \"%ws\"\n", g.MachineName);
  2517. wprintf(L"ARGS: UserName = \"%ws\"\n", g.UserName);
  2518. wprintf(L"ARGS: Password = \"%ws\"\n", g.Password);
  2519. wprintf(L"ARGS: AdapterGuid = \"%ws\"\n", g.AdapterGuid);
  2520. wprintf(L"ARGS: fReadPassword = %lu\n", g.fReadPassword);
  2521. wprintf(L"ARGS: fUseWmi = %lu\n", g.fUseWmi);
  2522. wprintf(L"ARGS: fLocalHost = %lu\n", g.fLocalHost);
  2523. wprintf(L"ARGS: fGotGuid = %lu\n", g.fGotGuid);
  2524. wprintf(L"ARGS: KEYWORD = %lu\n", (UINT) kw);
  2525. #endif // 0
  2526. if (kw == KW_UNKNOWN || kw == KW_HELP)
  2527. {
  2528. if (kw == KW_HELP)
  2529. {
  2530. do_usage();
  2531. }
  2532. goto end;
  2533. }
  2534. //
  2535. // If necessary, read password.
  2536. //
  2537. if (g.fReadPassword)
  2538. {
  2539. if (!read_password()) goto end;
  2540. // wprintf(L"ARGS2: Password = \"%ws\"\n", g.Password);
  2541. }
  2542. if (g.fUseWmi && !g.fLocalHost)
  2543. {
  2544. //
  2545. // Let's ping the host....
  2546. //
  2547. WBEMSTATUS Status;
  2548. ULONG uIpAddress;
  2549. wprintf(L"Pinging %ws...\n", g.MachineName);
  2550. Status = NlbHostPing(g.MachineName, 2000, &uIpAddress);
  2551. if (FAILED(Status))
  2552. {
  2553. wprintf(L"Ping failed\n");
  2554. goto end;
  2555. }
  2556. else
  2557. {
  2558. wprintf(L"Ping succeeded\n");
  2559. }
  2560. }
  2561. // kw = KW_QUIT;
  2562. while (kw != KW_QUIT)
  2563. {
  2564. switch(kw)
  2565. {
  2566. case KW_MAIN_SHELL:
  2567. kw = read_keyword(szMAIN_PROMPT);
  2568. break;
  2569. case KW_IPADDR: do_ipaddr();
  2570. break;
  2571. case KW_NLBCFG: do_nlbcfg();
  2572. break;
  2573. case KW_NLBBIND: do_nlbbind();
  2574. break;
  2575. case KW_ADAPTER_LIST: kw = parse_adapter_list();
  2576. break;
  2577. case KW_UPDATE: kw = parse_update();
  2578. break;
  2579. case KW_HELP:
  2580. kw = parse_main_help();
  2581. break;
  2582. case KW_UNKNOWN:
  2583. default:
  2584. printf(
  2585. "\"%ws\" is unexpected. Type \"help\""
  2586. " for more information.\n",
  2587. g.InputBuffer
  2588. );
  2589. kw = read_keyword(szMAIN_PROMPT);
  2590. break;
  2591. }
  2592. }
  2593. end:
  2594. return;
  2595. }
  2596. KEYWORD parse_adapter_list(VOID)
  2597. /*
  2598. Report adapter list and read next command.
  2599. */
  2600. {
  2601. KEYWORD kw = KW_UNKNOWN;
  2602. if (g.fUseWmi)
  2603. {
  2604. do_wminiclist(NULL, NULL);
  2605. }
  2606. else
  2607. {
  2608. do_niclist(NULL, NULL);
  2609. }
  2610. if (g.fRunOnce)
  2611. {
  2612. kw = KW_QUIT;
  2613. }
  2614. else
  2615. {
  2616. kw = read_keyword(szMAIN_PROMPT);
  2617. }
  2618. return kw;
  2619. }
  2620. VOID display_update_help(VOID);
  2621. VOID parse_network_addresses(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg,
  2622. BOOL *pfModified);
  2623. VOID parse_modify_network_address(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg,
  2624. BOOL *pfModified);
  2625. VOID parse_nlb_bound(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg);
  2626. VOID parse_cluster_network_address(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg);
  2627. VOID parse_cluster_name(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg);
  2628. VOID parse_traffic_mode(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg);
  2629. VOID parse_port_rules(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg);
  2630. VOID parse_host_priority(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg);
  2631. VOID parse_dedicated_network_address(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg);
  2632. VOID parse_cluster_mode_on_start(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg);
  2633. VOID parse_persist_suspend_on_reboot(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg);
  2634. VOID parse_remote_control_enabled(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg);
  2635. VOID parse_remote_password(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg);
  2636. void
  2637. parse_control(
  2638. BOOL fWmi,
  2639. PWMI_CONNECTION_INFO pConnInfo,
  2640. LPCWSTR szNicGuid
  2641. );
  2642. void
  2643. parse_query(
  2644. BOOL fWmi,
  2645. PWMI_CONNECTION_INFO pConnInfo,
  2646. LPCWSTR szNicGuid
  2647. );
  2648. KEYWORD parse_update(VOID)
  2649. #if 0
  2650. nlbcfg> update {guid}
  2651. Enter Adapter GUID: {guid}
  2652. NLB Configuration for Adapter xxxx xxxx:
  2653. Enter updated configuration, or type help for more information.
  2654. nlbcfg update> cna=10.0.0.1/255.255.255.0
  2655. nlbcfg update> cna=10.0.0.1/255.255.255.0
  2656. nlbcfg update> cna=10.0.0.1/255.255.255.0
  2657. nlbcfg update> .
  2658. Proposed new configuration:
  2659. .....
  2660. Enter y to confirm:
  2661. nlbcfg update> y
  2662. Going to perform update
  2663. ...
  2664. ....
  2665. complete
  2666. Reading configuration:
  2667. .......
  2668. Enter updated configuration or other command.
  2669. nlbcfg update>q
  2670. #endif // 0
  2671. {
  2672. BOOL fUseWmi = g.fUseWmi;
  2673. BOOL fLocal = g.fLocalHost;
  2674. LPCWSTR szNicGuid = g.AdapterGuid;
  2675. WBEMSTATUS Status;
  2676. WBEMSTATUS CompletionStatus;
  2677. UINT Generation;
  2678. WMI_CONNECTION_INFO ConnInfo;
  2679. PWMI_CONNECTION_INFO pConnInfo = NULL;
  2680. WCHAR LocalName[MAX_COMPUTERNAME_LENGTH + 1];
  2681. DWORD dwLen=ARRAY_LENGTH(LocalName);
  2682. BOOL fUserSetNetworkAddresses = FALSE;
  2683. BOOL fModified = FALSE;
  2684. BOOL fCheckNewConfiguration = FALSE;
  2685. //
  2686. // Skip reading the GUID if we've got it from the command line.
  2687. //
  2688. if (!g.fGotGuid)
  2689. {
  2690. if (g.fGotFriendlyName)
  2691. {
  2692. if (!get_guid_by_friendly_name())
  2693. {
  2694. printf(
  2695. "Could not find adapter with name \"%ws\"\n",
  2696. g.FriendlyName
  2697. );
  2698. goto end;
  2699. }
  2700. }
  2701. else
  2702. {
  2703. LPWSTR szNic = NULL;
  2704. if (!read_guid(&szNic)) goto end;
  2705. ARRAYSTRCPY(g.AdapterGuid, szNic);
  2706. delete szNic;
  2707. szNic=NULL;
  2708. }
  2709. }
  2710. if (!GetComputerName(LocalName, &dwLen))
  2711. {
  2712. ARRAYSTRCPY(LocalName, L"TPROV.EXE");
  2713. }
  2714. ZeroMemory(&ConnInfo, sizeof(ConnInfo));
  2715. if (fUseWmi && !fLocal)
  2716. {
  2717. ConnInfo.szMachine = g.MachineName;
  2718. if (g.UserName[0])
  2719. {
  2720. ConnInfo.szUserName = g.UserName;
  2721. ConnInfo.szPassword = g.Password;
  2722. }
  2723. pConnInfo = &ConnInfo;
  2724. }
  2725. start:
  2726. KEYWORD kw = KW_UNKNOWN;
  2727. WCHAR *pLog = NULL;
  2728. BOOL fSetDefaults = FALSE;
  2729. BOOL fUnbind = FALSE;
  2730. BOOL fConfigInputDone = FALSE;
  2731. //
  2732. // Clean up config info
  2733. //
  2734. MyOldCfg.Clear();
  2735. MyNewCfg.Clear();
  2736. MyBreak(L"Break before calling GetConfiguration.\n");
  2737. if (!fUseWmi)
  2738. {
  2739. Status = NlbConfigurationUpdate::GetConfiguration(
  2740. szNicGuid,
  2741. &MyOldCfg
  2742. );
  2743. }
  2744. else
  2745. {
  2746. Status = NlbHostGetConfiguration(
  2747. pConnInfo,
  2748. szNicGuid,
  2749. &MyOldCfg
  2750. );
  2751. }
  2752. if (FAILED(Status))
  2753. {
  2754. wprintf(L"Could not get configuration for Adapter %ws\n", szNicGuid);
  2755. goto end;
  2756. }
  2757. display_config2(szNicGuid, &MyOldCfg);
  2758. //
  2759. // 6/2002 JosephJ Following disabled because of false failures reported
  2760. // need to investigate further.
  2761. //
  2762. if (0 && fCheckNewConfiguration)
  2763. {
  2764. //
  2765. // Check MyOldCfg against MyNewCfg -- report a problem if
  2766. // they are NOT equivalent.
  2767. //
  2768. NLBERROR nerr;
  2769. BOOL fConnectivityChange = FALSE;
  2770. nerr = MyOldCfg.AnalyzeUpdate(
  2771. &MyNewCfg,
  2772. &fConnectivityChange
  2773. );
  2774. if (nerr != NLBERR_NO_CHANGE)
  2775. {
  2776. wprintf(L"WARNING: New parameters may not match requested parameters\n");
  2777. g_nRetCode = RETCODE_NEW_CONFIG_DOESNT_MATCH;
  2778. }
  2779. else
  2780. {
  2781. wprintf(L"New parameters match requested parameters!\n");
  2782. }
  2783. }
  2784. fCheckNewConfiguration = FALSE;
  2785. if (MyOldCfg.fBound)
  2786. {
  2787. if (!MyOldCfg.fValidNlbCfg)
  2788. {
  2789. //
  2790. // We're bound, but nlb params are bad. Set defaults.
  2791. //
  2792. wprintf(L"NLB is bound, but NLB parameters appear to be bad. Setting defaults\n");
  2793. fSetDefaults = TRUE;
  2794. }
  2795. }
  2796. else
  2797. {
  2798. //
  2799. // We're previously unbound. Set defaults.
  2800. //
  2801. fSetDefaults = TRUE;
  2802. }
  2803. //
  2804. // We setup the new configuration based on the old configuration, but
  2805. // additionally (if required) set the NLB params to default values,
  2806. // whether-or-not NLB is bound.
  2807. //
  2808. MyNewCfg.Update(&MyOldCfg); // copy
  2809. //
  2810. // We zap the network address list.
  2811. // We'll pick up the old ones IF the user hasn't changed them.
  2812. //
  2813. MyNewCfg.SetNetworkAddresses(NULL, 0);
  2814. if (fSetDefaults)
  2815. {
  2816. CfgUtilInitializeParams(&MyNewCfg.NlbParams);
  2817. MyNewCfg.fValidNlbCfg = TRUE;
  2818. }
  2819. else
  2820. {
  2821. ASSERT(MyNewCfg.fBound == TRUE);
  2822. }
  2823. ASSERT(MyNewCfg.fValidNlbCfg == TRUE);
  2824. wprintf(L"Enter updated configuration, or type help for more information.\n");
  2825. //
  2826. // We accept changes to the configuration in a loop.
  2827. // We get out of the loop when the user types "." or "quit"
  2828. //
  2829. do
  2830. {
  2831. #define szUPDATE_PROMPT L"nlbcfg update> "
  2832. kw = read_keyword(szUPDATE_PROMPT);
  2833. switch(kw)
  2834. {
  2835. case KW_QUIT:
  2836. printf("quit\n");
  2837. fConfigInputDone = TRUE;
  2838. break;
  2839. case KW_DOT:
  2840. printf("END OF CONFIG INPUT\n");
  2841. fConfigInputDone = TRUE;
  2842. break;
  2843. case KW_HELP:
  2844. display_update_help();
  2845. break;
  2846. case KW_NETWORK_ADDRESSES:
  2847. fModified = FALSE;
  2848. parse_network_addresses(&MyNewCfg, &fModified);
  2849. if (fModified)
  2850. {
  2851. fUserSetNetworkAddresses = TRUE;
  2852. }
  2853. break;
  2854. case KW_MODIFY_NETWORK_ADDRESS:
  2855. fModified = FALSE;
  2856. parse_modify_network_address(&MyNewCfg, &fModified);
  2857. if (fModified)
  2858. {
  2859. fUserSetNetworkAddresses = TRUE;
  2860. }
  2861. break;
  2862. #if 0
  2863. case KW_PARTIAL_UPDATE:
  2864. printf("partial update\n");
  2865. break;
  2866. #endif // 0
  2867. case KW_NLB_BOUND:
  2868. parse_nlb_bound(&MyNewCfg);
  2869. break;
  2870. case KW_CLUSTER_NETWORK_ADDRESS:
  2871. parse_cluster_network_address(&MyNewCfg);
  2872. break;
  2873. case KW_CLUSTER_NAME:
  2874. parse_cluster_name(&MyNewCfg);
  2875. break;
  2876. case KW_TRAFFIC_MODE:
  2877. parse_traffic_mode(&MyNewCfg);
  2878. break;
  2879. case KW_PORT_RULES:
  2880. parse_port_rules(&MyNewCfg);
  2881. break;
  2882. case KW_HOST_PRIORITY:
  2883. parse_host_priority(&MyNewCfg);
  2884. break;
  2885. case KW_DEDICATED_NETWORK_ADDRESS:
  2886. parse_dedicated_network_address(&MyNewCfg);
  2887. break;
  2888. case KW_CLUSTER_MODE_ON_START:
  2889. parse_cluster_mode_on_start(&MyNewCfg);
  2890. break;
  2891. case KW_PERSIST_SUSPEND_ON_REBOOT:
  2892. parse_persist_suspend_on_reboot(&MyNewCfg);
  2893. break;
  2894. case KW_REMOTE_CONTROL_ENABLED:
  2895. parse_remote_control_enabled(&MyNewCfg);
  2896. break;
  2897. case KW_PASSWORD:
  2898. parse_remote_password(&MyNewCfg);
  2899. break;
  2900. case KW_LIST:
  2901. display_config2(szNicGuid, &MyNewCfg);
  2902. break;
  2903. case KW_CONTROL:
  2904. parse_control(fUseWmi, pConnInfo, szNicGuid); // actually do op
  2905. break;
  2906. case KW_QUERY:
  2907. parse_query(fUseWmi, pConnInfo, szNicGuid);
  2908. break;
  2909. case KW_UNKNOWN:
  2910. default:
  2911. printf("unknown command \"%ws\"!\n", g.InputBuffer);
  2912. break;
  2913. }
  2914. } while (!fConfigInputDone);
  2915. if (kw == KW_QUIT)
  2916. {
  2917. goto end;
  2918. }
  2919. if (MyOldCfg.IsNlbBound() == MyNewCfg.IsNlbBound())
  2920. {
  2921. if (!fUserSetNetworkAddresses)
  2922. {
  2923. LPWSTR *pszOldAddresses = NULL;
  2924. UINT NumOldAddresses = 0;
  2925. ASSERT(MyNewCfg.NumIpAddresses == 0);
  2926. Status = MyOldCfg.GetNetworkAddresses(
  2927. &pszOldAddresses,
  2928. &NumOldAddresses
  2929. );
  2930. if (FAILED(Status))
  2931. {
  2932. wprintf(L"Error extracting old IP addresses\n");
  2933. NumOldAddresses = 0;
  2934. pszOldAddresses = NULL;
  2935. }
  2936. MyNewCfg.SetNetworkAddresses(
  2937. (LPCWSTR*)pszOldAddresses,
  2938. NumOldAddresses
  2939. );
  2940. delete pszOldAddresses;
  2941. pszOldAddresses=NULL;
  2942. }
  2943. }
  2944. else if (!MyNewCfg.IsNlbBound())
  2945. {
  2946. //
  2947. // We're to unbind.
  2948. //
  2949. if (!fUserSetNetworkAddresses)
  2950. {
  2951. //
  2952. // Set the list of ip address to have present on unbind to
  2953. // be the dedicated ip address, if there is one, otherwise zero,
  2954. // in which case the adapter will be switched to DHCP after NLB
  2955. // is unbound
  2956. //
  2957. ASSERT(MyNewCfg.NumIpAddresses == 0);
  2958. if (MyOldCfg.NlbParams.ded_ip_addr[0]!=0)
  2959. {
  2960. NLB_IP_ADDRESS_INFO *pIpInfo;
  2961. pIpInfo = new NLB_IP_ADDRESS_INFO;
  2962. if (pIpInfo == NULL)
  2963. {
  2964. printf("TEST: allocation failure; can't add IP on unbind.\n");
  2965. }
  2966. else
  2967. {
  2968. ARRAYSTRCPY(pIpInfo->IpAddress, MyOldCfg.NlbParams.ded_ip_addr);
  2969. ARRAYSTRCPY(pIpInfo->SubnetMask, MyOldCfg.NlbParams.ded_net_mask);
  2970. MyNewCfg.NumIpAddresses = 1;
  2971. MyNewCfg.pIpAddressInfo = pIpInfo;
  2972. }
  2973. }
  2974. }
  2975. }
  2976. display_config2(szNicGuid, &MyNewCfg);
  2977. kw = read_keyword(L"Begin update? ");
  2978. while (kw!=KW_YES && kw!=KW_NO)
  2979. {
  2980. kw = read_keyword(L"Enter yes or no: ");
  2981. }
  2982. if (kw == KW_NO) goto start; // TODO: get rid of these gotos!
  2983. MyBreak(L"Break before calling DoUpdate.\n");
  2984. //
  2985. // Set the AddDedicateIp and AddClusterIps fields.
  2986. //
  2987. MyNewCfg.fAddDedicatedIp = TRUE;
  2988. MyNewCfg.fAddClusterIps = TRUE;
  2989. if (!fUseWmi)
  2990. {
  2991. Status = NlbConfigurationUpdate::DoUpdate(
  2992. szNicGuid,
  2993. LocalName,
  2994. &MyNewCfg,
  2995. &Generation,
  2996. &pLog
  2997. );
  2998. }
  2999. else
  3000. {
  3001. Status = NlbHostDoUpdate(
  3002. pConnInfo,
  3003. szNicGuid,
  3004. LocalName,
  3005. &MyNewCfg,
  3006. &Generation,
  3007. &pLog
  3008. );
  3009. }
  3010. if (pLog != NULL)
  3011. {
  3012. display_log(pLog);
  3013. delete pLog;
  3014. pLog = NULL;
  3015. }
  3016. if (Status == WBEM_S_PENDING)
  3017. {
  3018. printf(
  3019. "Waiting for pending operation %d...\n",
  3020. Generation
  3021. );
  3022. }
  3023. while (Status == WBEM_S_PENDING)
  3024. {
  3025. Sleep(1000);
  3026. if (!fUseWmi)
  3027. {
  3028. Status = NlbConfigurationUpdate::GetUpdateStatus(
  3029. szNicGuid,
  3030. Generation,
  3031. FALSE, // FALSE == Don't delete completion record
  3032. &CompletionStatus,
  3033. &pLog
  3034. );
  3035. }
  3036. else
  3037. {
  3038. Status = NlbHostGetUpdateStatus(
  3039. pConnInfo,
  3040. szNicGuid,
  3041. Generation,
  3042. &CompletionStatus,
  3043. &pLog
  3044. );
  3045. }
  3046. if (pLog != NULL)
  3047. {
  3048. display_log(pLog);
  3049. delete pLog;
  3050. pLog = NULL;
  3051. }
  3052. if (!FAILED(Status))
  3053. {
  3054. Status = CompletionStatus;
  3055. }
  3056. }
  3057. printf(
  3058. "Final status of update %d is 0x%08lx\n",
  3059. Generation,
  3060. Status
  3061. );
  3062. if (FAILED(Status))
  3063. {
  3064. g_nRetCode = RETCODE_UPDATE_FAILED;
  3065. }
  3066. else
  3067. {
  3068. fCheckNewConfiguration = TRUE;
  3069. g_nRetCode = RETCODE_NO_ERROR;
  3070. }
  3071. goto start;
  3072. end:
  3073. if (g.fRunOnce)
  3074. {
  3075. kw = KW_QUIT;
  3076. }
  3077. else
  3078. {
  3079. kw = read_keyword(szMAIN_PROMPT);
  3080. }
  3081. return kw;
  3082. }
  3083. VOID display_update_help(VOID)
  3084. {
  3085. wprintf(L"\nNlbCfg update-specific commands\n");
  3086. wprintf(L" Help\n");
  3087. wprintf(L" ; <comment text>\n");
  3088. wprintf(L" na|NetworkAddresses = <list of IP addresses and subnets>\n");
  3089. wprintf(L" nb|NlbBound = true | false\n");
  3090. wprintf(L" cn|ClusterName = <cluster domain name>\n");
  3091. wprintf(L" tm|TrafficMode = UNICAST | MULTICAST | IGMPMULTICAST\n");
  3092. wprintf(L" pr|PortRules = <list of port rules>\n");
  3093. wprintf(L" hp|HostPriority = <host priority>\n");
  3094. wprintf(L" ps|PersistSuspend = true | false\n");
  3095. wprintf(L" dna|DedicatedNetworkAddress = <dedicated IP address and subnet>\n");
  3096. wprintf(L" cmos|ClusterModeOnStart = true | false\n");
  3097. wprintf(L" rce|RemoteControlEnabled = true | false\n");
  3098. wprintf(L" p|Password = <remote control password>\n");
  3099. wprintf(L" cl|Control start(st) | stop(sp) | drainstop(ds) | suspend(su) | resume(re) | query(qu) \n");
  3100. wprintf(L" cl|Control [vip=<ip-addr>] port=<port> enable(en) | disable(di) | drain(dn) | query(qu) \n");
  3101. wprintf(L" Query -- queries for cluster members\n");
  3102. wprintf(L" q|Quit\n");
  3103. wprintf(L"\nExample:\n");
  3104. wprintf(L" ; this is a comment\n");
  3105. wprintf(L" NlbBound = true\n");
  3106. wprintf(L" nb = true (equivalent to the above)\n");
  3107. wprintf(L" NetworkAddresses = {10.1.0.6/255.255.0.0, 10.1.0.66/255.255.0.0}\n");
  3108. wprintf(L" ClusterNetworkAddress = 10.1.0.66/255.255.0.0\n");
  3109. wprintf(L" ClusterName = cluster.domain.com\n");
  3110. wprintf(L" TrafficMode = UNICAST\n");
  3111. wprintf(L" PortRules =\n");
  3112. wprintf(L" {\n");
  3113. wprintf(L" ip=10.0.1.1 protocol=TCP start=80 end=288 mode=SINGLE priority=1\n");
  3114. wprintf(L" }\n");
  3115. wprintf(L" HostPriority = 1\n");
  3116. wprintf(L" DedicatedNetworkAddress = 10.1.0.6/255.255.0.0\n");
  3117. wprintf(L" ClusterModeOnStart = true\n");
  3118. wprintf(L" RemoteControlEnabled = false\n");
  3119. wprintf(L" cl start\n");
  3120. wprintf(L" cl vip=10.1.1.1 port=80 drain\n");
  3121. wprintf(L" cl port=80 disable\n");
  3122. wprintf(L" Query\n");
  3123. }
  3124. VOID parse_network_addresses(
  3125. NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg,
  3126. BOOL *pfModified
  3127. )
  3128. #if 0
  3129. Input format (the NetworkAddresses part has already been read)
  3130. NetworkAddresses = {
  3131. 10.0.0.1/255.0.0.0,
  3132. 10.0.0.2/255.0.0.0,
  3133. 10.0.0.3/255.0.0.0,
  3134. }
  3135. #endif // 0
  3136. {
  3137. #define MAX_INPUT_ADDRESSES 20
  3138. LPWSTR *pszAddresses = NULL;
  3139. UINT Count=0;
  3140. *pfModified = FALSE;
  3141. #define MY_MAX_NETWORK_ADDRESS_LENGTH \
  3142. (WLBS_MAX_CL_IP_ADDR + 1 + WLBS_MAX_CL_NET_MASK)
  3143. pszAddresses = CfgUtilsAllocateStringArray(
  3144. MAX_INPUT_ADDRESSES,
  3145. MY_MAX_NETWORK_ADDRESS_LENGTH
  3146. );
  3147. if (pszAddresses == NULL)
  3148. {
  3149. wprintf(L"Memory Allocation Failure.\n");
  3150. goto end;
  3151. }
  3152. //
  3153. // Look for = and open brace
  3154. //
  3155. if (wscanf(L" = %1[{]", g.InputBuffer) != 1) // -}-
  3156. {
  3157. goto end_bad_input;
  3158. }
  3159. //
  3160. // Read a list of comma-separated ipaddresses/subnets
  3161. //
  3162. BOOL fDone = FALSE;
  3163. while (!fDone && Count<MAX_INPUT_ADDRESSES)
  3164. {
  3165. LPWSTR szAddr = pszAddresses[Count];
  3166. WCHAR IpAddress[32];
  3167. WCHAR SubnetMask[32];
  3168. BOOL fGotAddr = FALSE;
  3169. INT i = wscanf(
  3170. L" %15[0-9.] / %15[0-9.] ",
  3171. IpAddress,
  3172. SubnetMask
  3173. );
  3174. if (i==2)
  3175. {
  3176. StringCchPrintf(
  3177. szAddr,
  3178. MY_MAX_NETWORK_ADDRESS_LENGTH,
  3179. L"%ws/%ws", IpAddress, SubnetMask);
  3180. fGotAddr = TRUE;
  3181. Count++;
  3182. }
  3183. else if (i==1)
  3184. {
  3185. wprintf(L"Missing subnet mask.\n");
  3186. goto end;
  3187. }
  3188. //
  3189. // Look for , or open-brace
  3190. //
  3191. i = wscanf(L" %1[},]", g.InputBuffer); // -{-
  3192. if (i == 1)
  3193. {
  3194. if (*g.InputBuffer == '}') // -{-
  3195. {
  3196. fDone = TRUE;
  3197. }
  3198. else if (!fGotAddr || *g.InputBuffer != ',')
  3199. {
  3200. wprintf(L"\"%ws\" unexpected.\n", g.InputBuffer);
  3201. goto end;
  3202. }
  3203. }
  3204. else
  3205. {
  3206. goto end_bad_input;
  3207. }
  3208. }
  3209. //
  3210. // We've got zero or more ip addresses. Let's set em.
  3211. //
  3212. WBEMSTATUS Status;
  3213. Status = pCfg->SetNetworkAddresses((LPCWSTR*)pszAddresses, Count);
  3214. if (FAILED(Status))
  3215. {
  3216. wprintf(L"Error 0x%08lx copying network addresses\n", (UINT) Status);
  3217. }
  3218. else
  3219. {
  3220. *pfModified = TRUE;
  3221. }
  3222. #if 0
  3223. UINT AddrCount = pCfg->NumIpAddresses;
  3224. display_ip_info2(AddrCount, pCfg->pIpAddressInfo);
  3225. #endif // 0
  3226. goto end;
  3227. end_bad_input:
  3228. if (wscanf(L"% 100ws", g.InputBuffer)!=1)
  3229. {
  3230. *g.InputBuffer = 0;
  3231. }
  3232. wprintf(L"\"%ws\" unexpected.\n", g.InputBuffer);
  3233. // fall through...
  3234. end:
  3235. delete pszAddresses;
  3236. pszAddresses = NULL;
  3237. return;
  3238. }
  3239. VOID parse_modify_network_address(
  3240. NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg,
  3241. BOOL *pfModified
  3242. )
  3243. #if 0
  3244. Input format (the ModifyNetworkAddress part has already been read)
  3245. ModifyNetworkAddress = 10.0.0.1, 10.0.0.2/255.0.0.0
  3246. ModifyNetworkAddress = -, 10.0.0.2/255.0.0.0
  3247. ModifyNetworkAddress = 10.0.0.1, -
  3248. ModifyNetworkAddress = -,-
  3249. #endif // 0
  3250. {
  3251. WCHAR rgOldAddr[32];
  3252. WCHAR rgNewIpAddr[66];
  3253. WCHAR rgNewSubnetMask[32];
  3254. LPCWSTR szOldAddr = NULL;
  3255. LPCWSTR szNewIpAddr = NULL;
  3256. *pfModified = FALSE;
  3257. *rgOldAddr = 0;
  3258. *rgNewIpAddr = 0;
  3259. *rgNewSubnetMask = 0;
  3260. INT i = wscanf(L" = %15[0-9.-] ,", rgOldAddr);
  3261. if (i!=1)
  3262. {
  3263. goto end_bad_input;
  3264. }
  3265. i = wscanf(L" %15[0-9.-]", rgNewIpAddr);
  3266. if (i!=1)
  3267. {
  3268. goto end_bad_input;
  3269. }
  3270. if (_wcsicmp(rgNewIpAddr, L"-"))
  3271. {
  3272. i = wscanf(L" / %15[0-9.]", rgNewSubnetMask);
  3273. if (i!=1)
  3274. {
  3275. wprintf(L"Missing subnet mask.\n");
  3276. goto end_bad_input;
  3277. }
  3278. szNewIpAddr = rgNewIpAddr;
  3279. }
  3280. if (_wcsicmp(rgOldAddr, L"-"))
  3281. {
  3282. szOldAddr = rgOldAddr;
  3283. }
  3284. WBEMSTATUS Status;
  3285. #if 1
  3286. Status = pCfg->ModifyNetworkAddress(szOldAddr, szNewIpAddr,rgNewSubnetMask);
  3287. #else
  3288. {
  3289. BOOL fRet;
  3290. NlbIpAddressList IpList;
  3291. fRet = IpList.Set(pCfg->NumIpAddresses, pCfg->pIpAddressInfo, 0);
  3292. if (fRet)
  3293. {
  3294. fRet = IpList.Modify(szOldAddr, szNewIpAddr, rgNewSubnetMask);
  3295. }
  3296. if (fRet)
  3297. {
  3298. pCfg->SetNetworkAddressesRaw(NULL,0);
  3299. IpList.Extract(REF pCfg->NumIpAddresses, REF pCfg->pIpAddressInfo);
  3300. Status = WBEM_NO_ERROR;
  3301. }
  3302. else
  3303. {
  3304. Status = WBEM_E_CRITICAL_ERROR;
  3305. }
  3306. }
  3307. #endif
  3308. if (Status != WBEM_NO_ERROR)
  3309. {
  3310. printf("pCfg->ModifyNetworkAddress returns error 0x%08lx\n",
  3311. Status);
  3312. }
  3313. *pfModified = TRUE;
  3314. goto end;
  3315. end_bad_input:
  3316. if (wscanf(L"% 100ws", g.InputBuffer)!=1)
  3317. {
  3318. *g.InputBuffer = 0;
  3319. }
  3320. wprintf(
  3321. L"Invalid format. Format: [-|ip-address],[-|network-address]\n");
  3322. // fall through...
  3323. end:
  3324. return;
  3325. }
  3326. VOID parse_nlb_bound(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg)
  3327. /*
  3328. NlbBound = true | false
  3329. */
  3330. {
  3331. BOOL NlbBound = FALSE;
  3332. INT i = wscanf(
  3333. L" = %15s",
  3334. g.InputBuffer
  3335. );
  3336. if (i==1)
  3337. {
  3338. if (!_wcsicmp(g.InputBuffer, L"true") || !_wcsicmp(g.InputBuffer, L"t"))
  3339. {
  3340. NlbBound = TRUE;
  3341. }
  3342. else if (!_wcsicmp(g.InputBuffer, L"false") || !_wcsicmp(g.InputBuffer, L"f"))
  3343. {
  3344. NlbBound = FALSE;
  3345. }
  3346. else
  3347. {
  3348. wprintf(L"\"%ws\" unexpected.\n", g.InputBuffer);
  3349. goto end;
  3350. }
  3351. }
  3352. else
  3353. {
  3354. if (wscanf(L"% 100ws", g.InputBuffer)!=1)
  3355. {
  3356. *g.InputBuffer = 0;
  3357. }
  3358. wprintf(L"\"%ws\" unexpected.\n", g.InputBuffer);
  3359. goto end;
  3360. }
  3361. pCfg->SetNlbBound(NlbBound);
  3362. // wprintf(L"DBG: NlbBound=%lu\n", pCfg->IsNlbBound());
  3363. end:
  3364. return;
  3365. }
  3366. VOID parse_cluster_network_address(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg)
  3367. /*++
  3368. ClusterNetworkAddress = 10.0.0.0/255.255.255.255
  3369. --*/
  3370. {
  3371. WCHAR IpAddress[32];
  3372. WCHAR SubnetMask[32];
  3373. INT i = wscanf(
  3374. L" = %15[0-9.] / %15[0-9.]",
  3375. IpAddress,
  3376. SubnetMask
  3377. );
  3378. if (i==2)
  3379. {
  3380. StringCbPrintf(
  3381. g.InputBuffer,
  3382. sizeof(g.InputBuffer),
  3383. L"%ws/%ws", IpAddress, SubnetMask);
  3384. pCfg->SetClusterNetworkAddress(g.InputBuffer);
  3385. }
  3386. else if (i==1)
  3387. {
  3388. wprintf(L"Missing subnet mask.\n");
  3389. goto end;
  3390. }
  3391. else
  3392. {
  3393. if (wscanf(L"% 100ws", g.InputBuffer)!=1)
  3394. {
  3395. *g.InputBuffer = 0;
  3396. }
  3397. wprintf(L"\"%ws\" unexpected.\n", g.InputBuffer);
  3398. goto end;
  3399. }
  3400. if (!pCfg->IsNlbBound())
  3401. {
  3402. wprintf(L"Assuming NLB needs to be bound.\n");
  3403. pCfg->SetNlbBound(TRUE);
  3404. }
  3405. // DBG
  3406. {
  3407. LPWSTR szAddr = NULL;
  3408. WBEMSTATUS Status;
  3409. Status = pCfg->GetClusterNetworkAddress(&szAddr);
  3410. if (FAILED(Status))
  3411. {
  3412. printf("Couldn't get address!\n");
  3413. }
  3414. else
  3415. {
  3416. // wprintf(L"DBG: CNA=%ws\n", szAddr);
  3417. delete szAddr;
  3418. }
  3419. }
  3420. end:
  3421. return;
  3422. }
  3423. VOID parse_cluster_name(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg)
  3424. /*++
  3425. ClusterName = cluster.microsoft.com
  3426. --*/
  3427. {
  3428. INT i = wscanf(
  3429. L" = %ws",
  3430. g.InputBuffer
  3431. );
  3432. if (i==1)
  3433. {
  3434. pCfg->SetClusterName(g.InputBuffer);
  3435. }
  3436. else
  3437. {
  3438. if (wscanf(L"% 100ws", g.InputBuffer)!=1)
  3439. {
  3440. *g.InputBuffer = 0;
  3441. }
  3442. wprintf(L"\"%ws\" unexpected.\n", g.InputBuffer);
  3443. goto end;
  3444. }
  3445. if (!pCfg->IsNlbBound())
  3446. {
  3447. wprintf(L"Assuming NLB needs to be bound.\n");
  3448. pCfg->SetNlbBound(TRUE);
  3449. }
  3450. // DBG
  3451. {
  3452. LPWSTR szName = NULL;
  3453. WBEMSTATUS Status;
  3454. Status = pCfg->GetClusterName(&szName);
  3455. if (FAILED(Status))
  3456. {
  3457. printf("Couldn't get name!\n");
  3458. }
  3459. else
  3460. {
  3461. // wprintf(L"DBG: CN=%ws\n", szName);
  3462. delete szName;
  3463. }
  3464. }
  3465. end:
  3466. return;
  3467. }
  3468. VOID parse_traffic_mode(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg)
  3469. /*
  3470. TrafficMode = UNICAST | MULTICAST | IGMPMULTICAST
  3471. */
  3472. {
  3473. NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE TrafficMode;
  3474. INT i = wscanf(
  3475. L" = %ws",
  3476. g.InputBuffer
  3477. );
  3478. if (i==1)
  3479. {
  3480. if (!_wcsicmp(g.InputBuffer, L"UNICAST") || !_wcsicmp(g.InputBuffer, L"U"))
  3481. {
  3482. TrafficMode=NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_UNICAST;
  3483. }
  3484. else if (!_wcsicmp(g.InputBuffer, L"MULTICAST") || !_wcsicmp(g.InputBuffer, L"M"))
  3485. {
  3486. TrafficMode=NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_MULTICAST;
  3487. }
  3488. else if (!_wcsicmp(g.InputBuffer, L"IGMPMULTICAST") || !_wcsicmp(g.InputBuffer, L"I"))
  3489. {
  3490. TrafficMode=NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_IGMPMULTICAST;
  3491. }
  3492. else
  3493. {
  3494. wprintf(L"\"%ws\" unexpected.\n", g.InputBuffer);
  3495. goto end;
  3496. }
  3497. pCfg->SetTrafficMode(TrafficMode);
  3498. }
  3499. else
  3500. {
  3501. if (wscanf(L"% 100ws", g.InputBuffer)!=1)
  3502. {
  3503. *g.InputBuffer = 0;
  3504. }
  3505. wprintf(L"\"%ws\" unexpected.\n", g.InputBuffer);
  3506. goto end;
  3507. }
  3508. if (!pCfg->IsNlbBound())
  3509. {
  3510. wprintf(L"Assuming NLB needs to be bound.\n");
  3511. pCfg->SetNlbBound(TRUE);
  3512. }
  3513. // DBG
  3514. {
  3515. TrafficMode = pCfg->GetTrafficMode();
  3516. // wprintf(L"DBG: TrafficMode=%ld\n", (UINT) TrafficMode);
  3517. }
  3518. end:
  3519. return;
  3520. }
  3521. VOID parse_port_rules(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg)
  3522. {
  3523. #define MAX_PORT_RULES 32
  3524. LPWSTR *pszPortRules = NULL;
  3525. UINT Count=0;
  3526. #define MY_MAX_PORT_RULE_LENGTH 128
  3527. pszPortRules = CfgUtilsAllocateStringArray(
  3528. MAX_PORT_RULES,
  3529. MY_MAX_PORT_RULE_LENGTH
  3530. );
  3531. if (pszPortRules == NULL)
  3532. {
  3533. wprintf(L"Memory Allocation Failure.\n");
  3534. goto end;
  3535. }
  3536. //
  3537. // Look for = and open brace
  3538. //
  3539. if (wscanf(L" = %1[{]", g.InputBuffer) != 1) // -}-
  3540. {
  3541. goto end_bad_input;
  3542. }
  3543. //
  3544. // Read a list of comma-separated list of port rules
  3545. //
  3546. BOOL fDone = FALSE;
  3547. while (!fDone && Count<MAX_PORT_RULES)
  3548. {
  3549. LPWSTR szPR = pszPortRules[Count];
  3550. BOOL fGotPR = FALSE;
  3551. int i;
  3552. //
  3553. // We suck up everything until the first , or close-brace.
  3554. //
  3555. if (wscanf(L" %128[^},]", g.InputBuffer) == 1) // -{-
  3556. {
  3557. BOOL fRet = FALSE;
  3558. WLBS_PORT_RULE Pr;
  3559. // printf("DBG: Got \"%ws\"\n", g.InputBuffer);
  3560. fRet = CfgUtilsSetPortRuleString(
  3561. g.InputBuffer,
  3562. &Pr
  3563. );
  3564. if (fRet == FALSE)
  3565. {
  3566. wprintf(L"Invalid port rule: \"%ws\"\n", g.InputBuffer);
  3567. goto end;
  3568. }
  3569. Count++;
  3570. fGotPR = TRUE;
  3571. g.InputBuffer[MY_MAX_PORT_RULE_LENGTH] = 0;
  3572. StringCchCopy(szPR, MY_MAX_PORT_RULE_LENGTH, g.InputBuffer);
  3573. }
  3574. //
  3575. // Look for , or open-brace
  3576. //
  3577. i = wscanf(L" %1[},]", g.InputBuffer); // -{-
  3578. if (i == 1)
  3579. {
  3580. if (*g.InputBuffer == '}') // -{-
  3581. {
  3582. fDone = TRUE;
  3583. }
  3584. else if (!fGotPR || *g.InputBuffer != ',')
  3585. {
  3586. wprintf(L"\"%ws\" unexpected.\n", g.InputBuffer);
  3587. goto end;
  3588. }
  3589. }
  3590. else
  3591. {
  3592. goto end_bad_input;
  3593. }
  3594. }
  3595. if (!pCfg->IsNlbBound())
  3596. {
  3597. wprintf(L"Assuming NLB needs to be bound.\n");
  3598. pCfg->SetNlbBound(TRUE);
  3599. }
  3600. //
  3601. // We've got zero or more port rules. Let's set em.
  3602. //
  3603. WBEMSTATUS Status;
  3604. Status = pCfg->SetPortRules((LPCWSTR*)pszPortRules, Count);
  3605. if (FAILED(Status))
  3606. {
  3607. wprintf(L"Error 0x%08lx copying port rules\n", (UINT) Status);
  3608. }
  3609. // display_port_rules(pCfg);
  3610. goto end;
  3611. end_bad_input:
  3612. if (wscanf(L"% 100ws", g.InputBuffer)!=1)
  3613. {
  3614. *g.InputBuffer = 0;
  3615. }
  3616. wprintf(L"\"%ws\" unexpected.\n", g.InputBuffer);
  3617. // fall through...
  3618. end:
  3619. delete pszPortRules;
  3620. pszPortRules = NULL;
  3621. return;
  3622. }
  3623. VOID parse_host_priority(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg)
  3624. /*
  3625. HostPriority=10
  3626. */
  3627. {
  3628. UINT Pri = 0;
  3629. INT i = wscanf(
  3630. L" = %lu",
  3631. &Pri
  3632. );
  3633. if (i==1)
  3634. {
  3635. pCfg->SetHostPriority(Pri);
  3636. }
  3637. else
  3638. {
  3639. if (wscanf(L"% 100ws", g.InputBuffer)!=1)
  3640. {
  3641. *g.InputBuffer = 0;
  3642. }
  3643. wprintf(L"\"%ws\" unexpected.\n", g.InputBuffer);
  3644. goto end;
  3645. }
  3646. if (!pCfg->IsNlbBound())
  3647. {
  3648. wprintf(L"Assuming NLB needs to be bound.\n");
  3649. pCfg->SetNlbBound(TRUE);
  3650. }
  3651. // wprintf(L"DBG: HostPriority=%lu\n", pCfg->GetHostPriority());
  3652. end:
  3653. return;
  3654. }
  3655. VOID parse_dedicated_network_address(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg)
  3656. /*++
  3657. DedicatedNetworkAddress = 10.0.0.0/255.255.255.255
  3658. --*/
  3659. {
  3660. WCHAR IpAddress[32];
  3661. WCHAR SubnetMask[32];
  3662. INT i = wscanf(
  3663. L" = %15[0-9.] / %15[0-9.]",
  3664. IpAddress,
  3665. SubnetMask
  3666. );
  3667. if (i==2)
  3668. {
  3669. StringCbPrintf(
  3670. g.InputBuffer,
  3671. sizeof(g.InputBuffer),
  3672. L"%ws/%ws", IpAddress, SubnetMask);
  3673. pCfg->SetDedicatedNetworkAddress(g.InputBuffer);
  3674. }
  3675. else if (i==1)
  3676. {
  3677. wprintf(L"Missing subnet mask.\n");
  3678. goto end;
  3679. }
  3680. else
  3681. {
  3682. if (wscanf(L"% 100ws", g.InputBuffer)!=1)
  3683. {
  3684. *g.InputBuffer = 0;
  3685. }
  3686. wprintf(L"\"%ws\" unexpected.\n", g.InputBuffer);
  3687. goto end;
  3688. }
  3689. if (!pCfg->IsNlbBound())
  3690. {
  3691. wprintf(L"Assuming NLB needs to be bound.\n");
  3692. pCfg->SetNlbBound(TRUE);
  3693. }
  3694. // DBG
  3695. {
  3696. LPWSTR szAddr = NULL;
  3697. WBEMSTATUS Status;
  3698. Status = pCfg->GetDedicatedNetworkAddress(&szAddr);
  3699. if (FAILED(Status))
  3700. {
  3701. printf("Couldn't get address!\n");
  3702. }
  3703. else
  3704. {
  3705. // wprintf(L"DBG: DNA=%ws\n", szAddr);
  3706. delete szAddr;
  3707. }
  3708. }
  3709. end:
  3710. return;
  3711. }
  3712. VOID parse_cluster_mode_on_start(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg)
  3713. {
  3714. INT i = wscanf(
  3715. L" = %15s",
  3716. g.InputBuffer
  3717. );
  3718. if (i==1)
  3719. {
  3720. DWORD sm;
  3721. if (!_wcsicmp(g.InputBuffer, L"true") || !_wcsicmp(g.InputBuffer, L"t"))
  3722. {
  3723. sm = CVY_HOST_STATE_STARTED;
  3724. }
  3725. else if (!_wcsicmp(g.InputBuffer, L"false") || !_wcsicmp(g.InputBuffer, L"f"))
  3726. {
  3727. sm = CVY_HOST_STATE_STOPPED;
  3728. }
  3729. else if (!_wcsicmp(g.InputBuffer, L"suspend") || !_wcsicmp(g.InputBuffer, L"s"))
  3730. {
  3731. sm = CVY_HOST_STATE_SUSPENDED;
  3732. }
  3733. else
  3734. {
  3735. wprintf(L"\"%ws\" unexpected.\n", g.InputBuffer);
  3736. goto end;
  3737. }
  3738. pCfg->SetClusterModeOnStart(sm);
  3739. }
  3740. else
  3741. {
  3742. if (wscanf(L"% 100ws", g.InputBuffer)!=1)
  3743. {
  3744. *g.InputBuffer = 0;
  3745. }
  3746. wprintf(L"\"%ws\" unexpected.\n", g.InputBuffer);
  3747. goto end;
  3748. }
  3749. if (!pCfg->IsNlbBound())
  3750. {
  3751. wprintf(L"Assuming NLB needs to be bound.\n");
  3752. pCfg->SetNlbBound(TRUE);
  3753. }
  3754. // wprintf(L"DBG: CMOS=%lu\n", (INT) pCfg->GetClusterModeOnStart());
  3755. end:
  3756. return;
  3757. }
  3758. VOID parse_persist_suspend_on_reboot(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg)
  3759. {
  3760. INT i = wscanf(
  3761. L" = %15s",
  3762. g.InputBuffer
  3763. );
  3764. if (i==1)
  3765. {
  3766. BOOL ps;
  3767. if (!_wcsicmp(g.InputBuffer, L"true") || !_wcsicmp(g.InputBuffer, L"t"))
  3768. {
  3769. ps = TRUE;
  3770. }
  3771. else if (!_wcsicmp(g.InputBuffer, L"false") || !_wcsicmp(g.InputBuffer, L"f"))
  3772. {
  3773. ps = FALSE;
  3774. }
  3775. else
  3776. {
  3777. wprintf(L"\"%ws\" unexpected.\n", g.InputBuffer);
  3778. goto end;
  3779. }
  3780. pCfg->SetPersistSuspendOnReboot(ps);
  3781. }
  3782. else
  3783. {
  3784. if (wscanf(L"% 100ws", g.InputBuffer)!=1)
  3785. {
  3786. *g.InputBuffer = 0;
  3787. }
  3788. wprintf(L"\"%ws\" unexpected.\n", g.InputBuffer);
  3789. goto end;
  3790. }
  3791. if (!pCfg->IsNlbBound())
  3792. {
  3793. wprintf(L"Assuming NLB needs to be bound.\n");
  3794. pCfg->SetNlbBound(TRUE);
  3795. }
  3796. // wprintf(L"DBG: CMOS=%lu\n", (INT) pCfg->GetClusterModeOnStart());
  3797. end:
  3798. return;
  3799. }
  3800. VOID parse_remote_control_enabled(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg)
  3801. /*
  3802. RemoteControlEnabled = true | false
  3803. */
  3804. {
  3805. BOOL Enabled = FALSE;
  3806. INT i = wscanf(
  3807. L" = %15s",
  3808. g.InputBuffer
  3809. );
  3810. if (i==1)
  3811. {
  3812. if (!_wcsicmp(g.InputBuffer, L"true") || !_wcsicmp(g.InputBuffer, L"t"))
  3813. {
  3814. Enabled = TRUE;
  3815. }
  3816. else if (!_wcsicmp(g.InputBuffer, L"false") || !_wcsicmp(g.InputBuffer, L"f"))
  3817. {
  3818. Enabled = FALSE;
  3819. }
  3820. else
  3821. {
  3822. wprintf(L"\"%ws\" unexpected.\n", g.InputBuffer);
  3823. goto end;
  3824. }
  3825. }
  3826. else
  3827. {
  3828. if (wscanf(L"% 100ws", g.InputBuffer)!=1)
  3829. {
  3830. *g.InputBuffer = 0;
  3831. }
  3832. wprintf(L"\"%ws\" unexpected.\n", g.InputBuffer);
  3833. goto end;
  3834. }
  3835. if (!pCfg->IsNlbBound())
  3836. {
  3837. wprintf(L"Assuming NLB needs to be bound.\n");
  3838. pCfg->SetNlbBound(TRUE);
  3839. }
  3840. pCfg->SetRemoteControlEnabled(Enabled);
  3841. // wprintf(L"DBG: RemoteControlEnabled=%lu\n", pCfg->GetRemoteControlEnabled());
  3842. end:
  3843. return;
  3844. }
  3845. VOID parse_remote_password(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg)
  3846. /*
  3847. Password=blah
  3848. */
  3849. {
  3850. INT i = wscanf(
  3851. L" = %ws",
  3852. g.InputBuffer
  3853. );
  3854. if (i==1)
  3855. {
  3856. // TODO: This is unsuppoted.
  3857. // pCfg->SetPassword(g.InputBuffer);
  3858. wprintf(L"Unimplemented\n");
  3859. goto end;
  3860. }
  3861. else
  3862. {
  3863. if (wscanf(L"% 100ws", g.InputBuffer)!=1)
  3864. {
  3865. *g.InputBuffer = 0;
  3866. }
  3867. wprintf(L"\"%ws\" unexpected.\n", g.InputBuffer);
  3868. goto end;
  3869. }
  3870. if (!pCfg->IsNlbBound())
  3871. {
  3872. wprintf(L"Assuming NLB needs to be bound.\n");
  3873. pCfg->SetNlbBound(TRUE);
  3874. }
  3875. end:
  3876. return;
  3877. }
  3878. KEYWORD parse_main_help(VOID)
  3879. {
  3880. printf("Commands:\n");
  3881. printf(" AdapterList|al - displays a list of NLB-compatible adapters\n");
  3882. printf(" Update|u <guid> - displays current configuration for the specified\n"
  3883. " adapter and then accepts commands to update\n"
  3884. " that configuration\n");
  3885. printf(" Help|h|? - displays this help message\n");
  3886. printf(" Quit|q - exits the NLB configuration shell\n");
  3887. KEYWORD kw;
  3888. if (g.fRunOnce)
  3889. {
  3890. kw = KW_QUIT;
  3891. }
  3892. else
  3893. {
  3894. kw = read_keyword(szMAIN_PROMPT);
  3895. }
  3896. return kw;
  3897. }
  3898. #if 0
  3899. parse_wmiupdate()
  3900. {
  3901. COMMAND_TYPE Cmd;
  3902. read_guid();
  3903. // get config and display it
  3904. // read new config from stdin
  3905. do
  3906. {
  3907. Cmd = read_keyword();
  3908. switch(Cmd)
  3909. {
  3910. NETWORK_ADDRESSES:
  3911. DOT: // end of config change description
  3912. ADAPTER_LIST:
  3913. HELP:
  3914. fQuit=TRUE;
  3915. greak;
  3916. }
  3917. } while (!fQuit)
  3918. return Cmd;
  3919. }
  3920. #endif // 0
  3921. BOOL valid_guid(LPCWSTR szGuid)
  3922. {
  3923. UINT Len = wcslen(szGuid);
  3924. if (
  3925. Len!=NLB_GUID_LEN
  3926. || szGuid[0] != '{'
  3927. || szGuid[Len-1]!='}'
  3928. )
  3929. {
  3930. return FALSE;
  3931. }
  3932. return TRUE;
  3933. }
  3934. BOOL
  3935. GetPassword(
  3936. PWSTR szBuffer,
  3937. DWORD dwLength,
  3938. DWORD *pdwLengthReturn
  3939. )
  3940. /*
  3941. Reads the password from stdin, WITHOUT echoing the password chars to
  3942. stdiout.
  3943. JosephJ 6/3/01
  3944. Taken verbatim from \nt\ds\ds\src\util\csvds.
  3945. It was one of the dirs that showed up when I did an index search
  3946. for "Type the password for", which is what the "net use" command
  3947. prompts when asking for a password.
  3948. Works like a charm.
  3949. */
  3950. {
  3951. #define CR 0xD
  3952. #define BACKSPACE 0x8
  3953. #define NULLC '\0'
  3954. #define NEWLINE '\n'
  3955. WCHAR ch;
  3956. PWSTR pszBufCur = szBuffer;
  3957. DWORD c;
  3958. int err;
  3959. DWORD mode;
  3960. //
  3961. // make space for NULL terminator
  3962. //
  3963. dwLength -= 1;
  3964. *pdwLengthReturn = 0;
  3965. if (!GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE),
  3966. &mode)) {
  3967. return FALSE;
  3968. }
  3969. SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE),
  3970. (~(ENABLE_ECHO_INPUT|ENABLE_LINE_INPUT)) & mode);
  3971. while (TRUE) {
  3972. err = ReadConsole(GetStdHandle(STD_INPUT_HANDLE),
  3973. &ch,
  3974. 1,
  3975. &c,
  3976. 0);
  3977. if (!err || c != 1)
  3978. ch = 0xffff;
  3979. if ((ch == CR) || (ch == 0xffff)) // end of line
  3980. break;
  3981. if (ch == BACKSPACE) { // back up one or two
  3982. //
  3983. // IF pszBufCur == buf then the next two lines are a no op.
  3984. // Because the user has basically backspaced back to the start
  3985. //
  3986. if (pszBufCur != szBuffer) {
  3987. pszBufCur--;
  3988. (*pdwLengthReturn)--;
  3989. }
  3990. }
  3991. else {
  3992. *pszBufCur = ch;
  3993. if (*pdwLengthReturn < dwLength)
  3994. pszBufCur++ ; // don't overflow buf
  3995. (*pdwLengthReturn)++; // always increment pdwLengthReturn
  3996. }
  3997. }
  3998. SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), mode);
  3999. //
  4000. // NULL terminate the string
  4001. //
  4002. *pszBufCur = NULLC;
  4003. putchar(NEWLINE);
  4004. return((*pdwLengthReturn <= dwLength) ? TRUE : FALSE);
  4005. }
  4006. VOID
  4007. test_port_rule_string(VOID)
  4008. {
  4009. LPCWSTR RuleStrings[] =
  4010. {
  4011. L"",
  4012. L" \t \n ",
  4013. L"n=v",
  4014. L" \t \n n=v",
  4015. L" \t \n n \t \n = \t \n v",
  4016. L"na=v1 nb=v2 nc=v3",
  4017. L"\t na \t = \t v1 \t nb \t \n =\t \n v2 \t \n nc \t = \n v3 ",
  4018. #if 1
  4019. L"ip=1.1.1.1 protocol=TCP start=80 end=288 mode=SINGLE"
  4020. L" priority=1",
  4021. L"ip=1.1.1.1 protocol=UDP start=80 end=288 mode=MULTIPLE"
  4022. L" affinity=SINGLE load=80",
  4023. L"ip=1.1.1.1 protocol=UDP start=80 end=288 mode=MULTIPLE"
  4024. L" affinity=NONE load=80",
  4025. L"ip=1.1.1.1 protocol=UDP start=80 end=288 mode=MULTIPLE"
  4026. L" affinity=CLASSC",
  4027. L"ip=1.1.1.1 protocol=BOTH start=80 end=288 mode=DISABLED",
  4028. #endif // 0
  4029. NULL // Must be last
  4030. };
  4031. for (LPCWSTR *ppRs = RuleStrings; *ppRs!=NULL; ppRs++)
  4032. {
  4033. LPCWSTR szRule = *ppRs;
  4034. WCHAR szGenString[NLB_MAX_PORT_STRING_SIZE];
  4035. printf("ORIG: %ws\n", szRule);
  4036. WLBS_PORT_RULE Pr;
  4037. BOOL fRet;
  4038. fRet = CfgUtilsSetPortRuleString(
  4039. szRule,
  4040. &Pr
  4041. );
  4042. if (fRet == FALSE)
  4043. {
  4044. printf("CfgUtilsSetPortRuleString returned FAILURE.\n");
  4045. continue;
  4046. }
  4047. fRet = CfgUtilsGetPortRuleString(
  4048. &Pr,
  4049. szGenString
  4050. );
  4051. if (fRet == FALSE)
  4052. {
  4053. printf("CfgUtilsGetPortRuleString returned FAILURE.\n");
  4054. continue;
  4055. }
  4056. printf("GEN: %ws\n", szGenString);
  4057. }
  4058. }
  4059. BOOL
  4060. get_guid_by_friendly_name(VOID)
  4061. {
  4062. LPWSTR szGuid = NULL;
  4063. BOOL fRet = FALSE;
  4064. szGuid = L"{AD4DA14D-CAAE-42DD-97E3-5355E55247C2}";
  4065. if (g.fUseWmi)
  4066. {
  4067. do_wminiclist(g.FriendlyName, &szGuid);
  4068. }
  4069. else
  4070. {
  4071. do_niclist(g.FriendlyName, &szGuid);
  4072. }
  4073. if (szGuid != NULL)
  4074. {
  4075. ARRAYSTRCPY(g.AdapterGuid, szGuid);
  4076. // printf("FR=\"%ws\"; Guid=%ws\n", g.FriendlyName, g.AdapterGuid);
  4077. delete szGuid; szGuid = NULL;
  4078. fRet = TRUE;
  4079. }
  4080. return fRet;
  4081. }
  4082. void test_vectors(void)
  4083. {
  4084. vector<_bstr_t> v1;
  4085. vector<_bstr_t> v2;
  4086. vector<_bstr_t> *pv3 = new vector<_bstr_t>;
  4087. WCHAR szBlah[10];
  4088. ARRAYSTRCPY(szBlah, L"blah");
  4089. v1.push_back(szBlah);
  4090. v1.push_back(szBlah);
  4091. *pv3 = v1;
  4092. v2 = *pv3;
  4093. delete pv3;
  4094. for (int i = 0; i< v1.size(); i++)
  4095. {
  4096. LPCWSTR sz1 = v1[i];
  4097. LPCWSTR sz2 = v2[i];
  4098. printf("v1[%d] = 0x%p(%ws); v2[i] = 0x%p(%ws)\n", i, sz1, sz1, sz2, sz2);
  4099. v2[i] = L"";
  4100. sz2 = v2[i];
  4101. printf("v1[%d] = 0x%p(%ws); v2[i] = 0x%p(%ws)\n", i, sz1, sz1, sz2, sz2);
  4102. }
  4103. }
  4104. typedef ULONG ENGINEHANDLE;
  4105. class CInterfaceSpec
  4106. {
  4107. public:
  4108. _bstr_t bstrGuid;
  4109. };
  4110. void test_maps(void)
  4111. {
  4112. ENGINEHANDLE ehA = 1;
  4113. ENGINEHANDLE ehB = 3;
  4114. CInterfaceSpec iSpecA;
  4115. CInterfaceSpec iSpecB;
  4116. iSpecA.bstrGuid = _bstr_t(L"ISpecA");
  4117. iSpecB.bstrGuid = _bstr_t(L"ISpecB");
  4118. map< ENGINEHANDLE, CInterfaceSpec* > mymap;
  4119. mymap[ehA] = &iSpecA;
  4120. mymap[ehB] = &iSpecB;
  4121. printf("eh=%lu, &iSpec=0x%p, mymap[eh]=%p\n", ehA, &iSpecA, mymap[ehA]);
  4122. printf("eh=%lu, &iSpec=0x%p, mymap[eh]=%p\n", ehB, &iSpecB, mymap[ehB]);
  4123. map< ENGINEHANDLE, CInterfaceSpec* >::iterator iter;
  4124. for( iter = mymap.begin();
  4125. iter != mymap.end();
  4126. ++iter)
  4127. {
  4128. CInterfaceSpec *pISpec = (*iter).second;
  4129. ENGINEHANDLE eh = (*iter).first;
  4130. printf("ITER: (eh=%lu, pISpec=%p, guid=%ws)\n", eh, pISpec,
  4131. LPCWSTR(pISpec->bstrGuid));
  4132. }
  4133. }
  4134. void test_validate_network_address(void)
  4135. {
  4136. WCHAR rgAddress[256];
  4137. UINT uIpAddress=0;
  4138. UINT uSubnet=0;
  4139. UINT uDefaultSubnet=0;
  4140. WBEMSTATUS wStat;
  4141. printf("Enter network address; 'q' to quit\n:");
  4142. while (wscanf(L" %64ws", rgAddress)==1)
  4143. {
  4144. if (!_wcsicmp(rgAddress, L"q"))
  4145. {
  4146. break;
  4147. }
  4148. wStat = CfgUtilsValidateNetworkAddress(
  4149. rgAddress,
  4150. &uIpAddress,
  4151. &uSubnet,
  4152. &uDefaultSubnet
  4153. );
  4154. if (wStat != WBEM_NO_ERROR)
  4155. {
  4156. printf("CfgUtilsValidateNetworkAddress returns error 0x%08lx\n",
  4157. wStat);
  4158. }
  4159. else
  4160. {
  4161. LPBYTE szI= (LPBYTE)&uIpAddress;
  4162. LPBYTE szS= (LPBYTE)&uSubnet;
  4163. LPBYTE szD= (LPBYTE)&uDefaultSubnet;
  4164. printf(
  4165. "\"%ws\" ->"
  4166. "(%lu.%lu.%lu.%lu, %lu.%lu.%lu.%lu, %lu.%lu.%lu.%lu)\n",
  4167. rgAddress,
  4168. szI[0], szI[1], szI[2], szI[3],
  4169. szS[0], szS[1], szS[2], szS[3],
  4170. szD[0], szD[1], szD[2], szD[3]
  4171. );
  4172. }
  4173. printf(":");
  4174. }
  4175. }
  4176. VOID MapStatusToDescription(DWORD Status, _bstr_t &szDescr)
  4177. {
  4178. struct STATUS_DESCR_MAP
  4179. {
  4180. DWORD Status;
  4181. LPCSTR Description;
  4182. }
  4183. StatusDescrMap[] =
  4184. {
  4185. {WLBS_ALREADY, "WLBS_ALREADY"},
  4186. {WLBS_BAD_PARAMS, "WLBS_BAD_PARAMS"},
  4187. {WLBS_NOT_FOUND, "WLBS_NOT_FOUND"},
  4188. {WLBS_STOPPED, "WLBS_STOPPED"},
  4189. {WLBS_SUSPENDED, "WLBS_SUSPENDED"},
  4190. {WLBS_CONVERGING, "WLBS_CONVERGING"},
  4191. {WLBS_CONVERGED, "WLBS_CONVERGED (Non-Default)"},
  4192. {WLBS_DEFAULT, "WLBS_DEFAULT (Converged as Default)"},
  4193. {WLBS_BAD_PASSW, "WLBS_BAD_PASSW"},
  4194. {WLBS_DRAINING, "WLBS_DRAINING"},
  4195. {WLBS_DRAIN_STOP, "WLBS_DRAIN_STOP"},
  4196. {WLBS_DISCONNECTED, "WLBS_DISCONNECTED"},
  4197. {WLBS_FAILURE, "WLBS_FAILURE"},
  4198. {WLBS_REFUSED, "WLBS_REFUSED"},
  4199. {WLBS_OK, "WLBS_OK"},
  4200. {WLBS_IO_ERROR, "WLBS_IO_ERROR"},
  4201. {NLB_PORT_RULE_NOT_FOUND, "PORT_RULE_NOT_FOUND"},
  4202. {NLB_PORT_RULE_ENABLED, "PORT_RULE_ENABLED"},
  4203. {NLB_PORT_RULE_DISABLED, "PORT_RULE_DISABLED"},
  4204. {NLB_PORT_RULE_DRAINING, "PORT_RULE_DRAINING"}
  4205. };
  4206. for (int i=0; i<sizeof(StatusDescrMap) /sizeof(StatusDescrMap[0]); i++)
  4207. {
  4208. if (StatusDescrMap[i].Status == Status)
  4209. {
  4210. szDescr = StatusDescrMap[i].Description;
  4211. return;
  4212. }
  4213. }
  4214. //
  4215. // Default
  4216. //
  4217. {
  4218. char temp[256];
  4219. StringCbPrintfA(temp, sizeof(temp), "Unknown (%lu)",Status);
  4220. szDescr = temp;
  4221. }
  4222. return ;
  4223. }
  4224. void
  4225. parse_control(
  4226. BOOL fWmi,
  4227. PWMI_CONNECTION_INFO pConnInfo,
  4228. LPCWSTR szNicGuid
  4229. )
  4230. //
  4231. // control [ip=x] port=y enable/disable/drain/query/nop
  4232. // control start/stop/query/nop
  4233. //
  4234. {
  4235. KEYWORD kw;
  4236. BOOL fGotPort = FALSE;
  4237. BOOL fGotIp = FALSE;
  4238. BOOL fGotCmd = FALSE;
  4239. KEYWORD kwCmd = KW_UNKNOWN;
  4240. WCHAR rgIp[32];
  4241. LPCWSTR szIp = NULL;
  4242. DWORD dwPort = 0;
  4243. WBEMSTATUS Status = WBEM_NO_ERROR;
  4244. DWORD dwOperationStatus = 0;
  4245. DWORD dwClusterOrPortStatus = 0;
  4246. DWORD dwHostMap = 0;
  4247. DWORD *pdwPort = NULL;
  4248. *rgIp=0;
  4249. while (!fGotCmd)
  4250. {
  4251. kw = read_keyword(L"");
  4252. switch(kw)
  4253. {
  4254. case KW_START:
  4255. case KW_STOP:
  4256. case KW_DRAIN:
  4257. case KW_DRAIN_STOP:
  4258. case KW_SUSPEND:
  4259. case KW_RESUME:
  4260. case KW_ENABLE:
  4261. case KW_DISABLE:
  4262. case KW_QUERY:
  4263. fGotCmd = TRUE;
  4264. kwCmd = kw;
  4265. break;
  4266. case KW_VIP:
  4267. // Look for "=<ip address>", eg. "= 10.0.0.1"
  4268. if (fGotIp)
  4269. {
  4270. wprintf(L"control: duplicate IP specification\n");
  4271. goto end; // parse error
  4272. }
  4273. if (wscanf(L" = %15[0-9.]", rgIp) != 1)
  4274. {
  4275. wprintf(L"control: bad ip specification\n");
  4276. goto end;
  4277. }
  4278. szIp = rgIp;
  4279. fGotIp = TRUE;
  4280. // printf("GOT IP \"%ws\"\n", rgIp);
  4281. break;
  4282. case KW_PORT:
  4283. // Look for "=<port>", eg. " = 80"
  4284. if (fGotPort)
  4285. {
  4286. wprintf(L"control: duplicate port specification\n");
  4287. goto end; // parse error
  4288. }
  4289. if (wscanf(L" = %lu", &dwPort) != 1)
  4290. {
  4291. wprintf(L"control: bad port specification\n");
  4292. goto end;
  4293. }
  4294. pdwPort = &dwPort;
  4295. fGotPort = TRUE;
  4296. // printf("GOT PORT %lu\n", dwPort);
  4297. break;
  4298. default: // parse error
  4299. printf("control: unknown argument\n");
  4300. goto end;
  4301. }
  4302. }
  4303. //
  4304. // Param checking
  4305. //
  4306. switch(kwCmd)
  4307. {
  4308. case KW_START: // following are adapter-wide
  4309. case KW_STOP:
  4310. case KW_DRAIN_STOP:
  4311. case KW_SUSPEND:
  4312. case KW_RESUME:
  4313. if (fGotIp || fGotPort)
  4314. {
  4315. wprintf(L"control: unexpected port or ip\n");
  4316. goto end; // parse error;
  4317. }
  4318. break;
  4319. case KW_ENABLE: // following are port-specific
  4320. case KW_DISABLE:
  4321. case KW_DRAIN:
  4322. if (!fGotPort)
  4323. {
  4324. wprintf(L"control: missing port\n");
  4325. goto end; // parse error;
  4326. }
  4327. if (!fGotIp)
  4328. {
  4329. wprintf(L"Assuming \"All Vip\", ie. Vip=255.255.255.255\n");
  4330. szIp = L"255.255.255.255"; // Default - "All Vip"
  4331. }
  4332. break;
  4333. case KW_QUERY:
  4334. {
  4335. if (fGotIp && ! fGotPort)
  4336. {
  4337. wprintf(L"control: missing port\n");
  4338. goto end; // parse error;
  4339. }
  4340. if (!fGotIp && fGotPort)
  4341. {
  4342. wprintf(L"Assuming \"All Vip\", ie. Vip=255.255.255.255\n");
  4343. szIp = L"255.255.255.255"; // default -- all vip
  4344. }
  4345. }
  4346. break;
  4347. default:
  4348. // we don't expect to get here.
  4349. goto end;
  4350. }
  4351. //
  4352. // Actually execute
  4353. //
  4354. {
  4355. WLBS_OPERATION_CODES Op = WLBS_START;
  4356. switch(kwCmd)
  4357. {
  4358. case KW_START:
  4359. // wprintf(L"DO START\n");
  4360. Op = WLBS_START;
  4361. break;
  4362. case KW_STOP:
  4363. Op = WLBS_STOP;
  4364. // wprintf(L"DO STOP\n");
  4365. break;
  4366. case KW_DRAIN_STOP:
  4367. Op = WLBS_DRAIN;
  4368. // wprintf(L"DO DRAIN STOP\n");
  4369. break;
  4370. case KW_SUSPEND:
  4371. Op = WLBS_SUSPEND;
  4372. // wprintf(L"DO SUSPEND\n");
  4373. break;
  4374. case KW_RESUME:
  4375. // wprintf(L"DO RESUME\n");
  4376. Op = WLBS_RESUME;
  4377. break;
  4378. case KW_ENABLE:
  4379. // wprintf(L"DO ENABLE\n");
  4380. Op = WLBS_PORT_ENABLE;
  4381. break;
  4382. case KW_DISABLE:
  4383. // wprintf(L"DO DISABLE\n");
  4384. Op = WLBS_PORT_DISABLE;
  4385. break;
  4386. case KW_DRAIN:
  4387. Op = WLBS_PORT_DRAIN;
  4388. // wprintf(L"DO DRAIN\n");
  4389. break;
  4390. case KW_QUERY:
  4391. if (fGotPort)
  4392. {
  4393. Op = WLBS_QUERY_PORT_STATE;
  4394. }
  4395. else
  4396. {
  4397. Op = WLBS_QUERY;
  4398. }
  4399. // wprintf(L"DO QUERY\n");
  4400. break;
  4401. default:
  4402. goto end; // don't expect to get here.
  4403. } // end switch
  4404. #define NEWSTUFF 1
  4405. #if NEWSTUFF
  4406. if (fWmi)
  4407. {
  4408. Status = NlbHostControlCluster(
  4409. pConnInfo,
  4410. szNicGuid,
  4411. szIp,
  4412. pdwPort,
  4413. Op,
  4414. &dwOperationStatus,
  4415. &dwClusterOrPortStatus,
  4416. &dwHostMap
  4417. );
  4418. }
  4419. else //
  4420. {
  4421. UINT uIp = 0;
  4422. if (!_wcsicmp(szIp, L"255.255.255.255")) // lazy eval
  4423. {
  4424. uIp = 0xffffffff; // all-vip
  4425. }
  4426. else
  4427. {
  4428. Status = CfgUtilsValidateNetworkAddress(szIp, &uIp, NULL, NULL);
  4429. if (FAILED(Status))
  4430. {
  4431. printf("control: invalid Ip address\n");
  4432. goto end;
  4433. }
  4434. }
  4435. switch(Op)
  4436. {
  4437. case WLBS_START:
  4438. case WLBS_STOP:
  4439. case WLBS_DRAIN:
  4440. case WLBS_SUSPEND:
  4441. case WLBS_RESUME:
  4442. CfgUtilControlCluster( szNicGuid, Op, 0, 0, NULL, &dwOperationStatus );
  4443. CfgUtilControlCluster( szNicGuid, WLBS_QUERY, 0, 0, &dwHostMap, &dwClusterOrPortStatus );
  4444. break;
  4445. case WLBS_PORT_ENABLE:
  4446. case WLBS_PORT_DISABLE:
  4447. case WLBS_PORT_DRAIN:
  4448. CfgUtilControlCluster( szNicGuid, Op, uIp, dwPort, NULL, &dwOperationStatus );
  4449. CfgUtilControlCluster( szNicGuid, WLBS_QUERY_PORT_STATE, uIp, dwPort, NULL, &dwClusterOrPortStatus );
  4450. break;
  4451. case WLBS_QUERY:
  4452. CfgUtilControlCluster( szNicGuid, WLBS_QUERY, 0, 0, &dwHostMap, &dwClusterOrPortStatus );
  4453. dwOperationStatus = WLBS_OK;
  4454. break;
  4455. case WLBS_QUERY_PORT_STATE:
  4456. default:
  4457. CfgUtilControlCluster( szNicGuid, WLBS_QUERY_PORT_STATE, uIp, dwPort, NULL, &dwClusterOrPortStatus );
  4458. dwOperationStatus = WLBS_OK;
  4459. break;
  4460. }
  4461. }
  4462. #endif // NEWSTUFF
  4463. if (FAILED(Status))
  4464. {
  4465. printf("ControlCluster returns failure 0x%08lx\n", Status);
  4466. }
  4467. else
  4468. {
  4469. _bstr_t szOperationStatusDescr, szClusterOrPortStatusStr;
  4470. MapStatusToDescription(dwOperationStatus, szOperationStatusDescr);
  4471. MapStatusToDescription(dwClusterOrPortStatus, szClusterOrPortStatusStr);
  4472. printf("ControlCluster returns Operation Status = %s\n",(LPCSTR)szOperationStatusDescr);
  4473. printf(" Cluster/Port State = %s\n",(LPCSTR)szClusterOrPortStatusStr);
  4474. printf(" Host Map = 0x%08lx\n",dwHostMap);
  4475. }
  4476. }
  4477. end:
  4478. return;
  4479. }
  4480. void
  4481. parse_query(
  4482. BOOL fWmi,
  4483. PWMI_CONNECTION_INFO pConnInfo,
  4484. LPCWSTR szNicGuid
  4485. )
  4486. //
  4487. // query -- list the members in the cluster
  4488. //
  4489. {
  4490. DWORD dwNumMembers = 0;
  4491. NLB_CLUSTER_MEMBER_INFO *pMembers = NULL;
  4492. WBEMSTATUS Status = WBEM_NO_ERROR;
  4493. if (fWmi)
  4494. {
  4495. Status = NlbHostGetClusterMembers(
  4496. pConnInfo,
  4497. szNicGuid,
  4498. &dwNumMembers,
  4499. &pMembers
  4500. );
  4501. }
  4502. else // !fWmi
  4503. {
  4504. Status = CfgUtilGetClusterMembers(
  4505. szNicGuid,
  4506. &dwNumMembers,
  4507. &pMembers
  4508. );
  4509. }
  4510. if (FAILED(Status))
  4511. {
  4512. printf("QueryCluster returns failure 0x%08lx\n", Status);
  4513. }
  4514. else
  4515. {
  4516. wprintf(L"HostID DedicatedIP HostName\n");
  4517. wprintf(L"-----------------------------------------------------\n");
  4518. DWORD dwHost = 0;
  4519. for (; dwHost < dwNumMembers; dwHost++)
  4520. {
  4521. wprintf(L"%-11d %-16ls %ls\n",
  4522. pMembers[dwHost].HostId,
  4523. (pMembers[dwHost].DedicatedIpAddress == NULL) ? L"" : pMembers[dwHost].DedicatedIpAddress,
  4524. (pMembers[dwHost].HostName == NULL) ? L"" : pMembers[dwHost].HostName
  4525. );
  4526. }
  4527. if (pMembers != NULL)
  4528. {
  4529. delete [] pMembers;
  4530. pMembers = NULL;
  4531. }
  4532. }
  4533. }
  4534. void display_nlbipaddresslist(
  4535. const NlbIpAddressList &IpList
  4536. )
  4537. {
  4538. BOOL fRet;
  4539. NlbIpAddressList IpListCopy;
  4540. NLB_IP_ADDRESS_INFO *pInfo=NULL;
  4541. UINT uNum=0;
  4542. fRet = IpListCopy.Copy(IpList);
  4543. if (!fRet) goto end;
  4544. IpListCopy.Extract(REF uNum, REF pInfo);
  4545. display_ip_info2(uNum, pInfo);
  4546. end:
  4547. delete pInfo;
  4548. }
  4549. void test_nlbipaddresslist(void)
  4550. {
  4551. BOOL fRet;
  4552. NlbIpAddressList IpList;
  4553. typedef struct
  4554. {
  4555. LPCWSTR szOld;
  4556. LPCWSTR szNew;
  4557. LPCWSTR szMask;
  4558. } MY_MODIFY_INFO;
  4559. #define MY_TERMINAL ((LPCWSTR) 0x1)
  4560. MY_MODIFY_INFO rgModInfo[] =
  4561. {
  4562. {NULL},
  4563. {NULL,L"1",L"11"},
  4564. {NULL,L"2",L"22"},
  4565. {NULL,L"3",L"33"},
  4566. {L"3",L"2", L"23"},
  4567. {L"2",L"1", L"13"},
  4568. {L"1",L"4", L"44"},
  4569. {L"1",L"4", L"44"},
  4570. {L"1",L"1", L"111"},
  4571. {L"3"},
  4572. {L"2"},
  4573. {L"1"},
  4574. {MY_TERMINAL} // must be last.
  4575. };
  4576. #if 0
  4577. for (MY_MODIFY_INFO *pModInfo = rgModInfo;
  4578. pModInfo->szOld != MY_TERMINAL;
  4579. pModInfo++
  4580. )
  4581. {
  4582. wprintf(
  4583. L"TRIAL: Old=\"%ws\" New=\"%ws\" Mask=\"%ws\"\n",
  4584. (pModInfo->szOld==NULL) ? L"<null>" : pModInfo->szOld,
  4585. (pModInfo->szNew==NULL) ? L"<null>" : pModInfo->szNew,
  4586. (pModInfo->szMask==NULL) ? L"<null>" : pModInfo->szMask
  4587. );
  4588. fRet = IpList.Modify(
  4589. pModInfo->szOld,
  4590. pModInfo->szNew,
  4591. pModInfo->szMask
  4592. );
  4593. display_nlbipaddresslist(IpList);
  4594. }
  4595. #endif // 0
  4596. NLB_IP_ADDRESS_INFO rgOrigInfo[] = {
  4597. {L"1", L"11"},
  4598. {L"2", L"22"},
  4599. {L"3", L"33"}
  4600. };
  4601. NLB_IP_ADDRESS_INFO rgNewInfo[] = {
  4602. {L"5", L"155"},
  4603. {L"4", L"144"},
  4604. {L"3", L"133"},
  4605. {L"2", L"122"},
  4606. };
  4607. #define ASIZE(_array) (sizeof(_array)/sizeof(_array[0]))
  4608. fRet = IpList.Set(ASIZE(rgOrigInfo), rgOrigInfo, 0);
  4609. // fRet = IpList.Set(0, NULL, 0);
  4610. if (!fRet)
  4611. {
  4612. goto end;
  4613. }
  4614. printf("Original List (before Apply):\n");
  4615. display_nlbipaddresslist(IpList);
  4616. fRet = IpList.Apply(ASIZE(rgNewInfo), rgNewInfo);
  4617. // fRet = IpList.Apply(0, NULL);
  4618. if (!fRet)
  4619. {
  4620. goto end;
  4621. }
  4622. printf("\nNew List (after Apply):\n");
  4623. display_nlbipaddresslist(IpList);
  4624. end:
  4625. if (fRet)
  4626. {
  4627. printf("display_nlbipaddresslist Test PASSED\n");
  4628. }
  4629. else
  4630. {
  4631. printf("display_nlbipaddresslist Test FAILED\n");
  4632. }
  4633. }
  4634. void test_ioctl_alignment(void)
  4635. {
  4636. //
  4637. // Just to check out the offsets of the following structures and sub-structures
  4638. // in the debugger to make sure that the packet versions are 8-byte aligned
  4639. //
  4640. //
  4641. IOCTL_CVY_BUF icb;
  4642. IOCTL_COMMON_OPTIONS ico;
  4643. IOCTL_REMOTE_OPTIONS iro;
  4644. IOCTL_REMOTE_HDR irh;
  4645. IOCTL_LOCAL_OPTIONS ilo;
  4646. IOCTL_LOCAL_HDR ilh;
  4647. NLB_OPTIONS_PORT_RULE_STATE prs;
  4648. NLB_OPTIONS_PACKET_FILTER pf;
  4649. }
  4650. void test_local_logger(void)
  4651. {
  4652. CLocalLogger logger;
  4653. LPCWSTR szLog = NULL;
  4654. //
  4655. // Warning: should match IDS_PROCESSING_UPDATE from ..\nlbmprov.h
  4656. //
  4657. #define IDS_PROCESING_UPDATE 200
  4658. for (UINT u = 1; u<50; u++)
  4659. {
  4660. logger.Log(IDS_PROCESING_UPDATE, u, L"test_local_logger");
  4661. }
  4662. szLog = logger.GetStringSafe();
  4663. wprintf(szLog);
  4664. }
  4665. void test_encrypt_memory(void)
  4666. {
  4667. BOOL fRet;
  4668. //
  4669. // JosephJ 4/10/02 Verified the following passwords as well...
  4670. // LPCWSTR szPwd = L"asdfasdfasdfasdfasdf asdf asdf asdfasdfasdf af a";
  4671. // LPCWSTR szPwd = L"1";
  4672. LPCWSTR szPwd = L"";
  4673. //
  4674. // LPCWSTR szPwd = L"password";
  4675. WCHAR rgEncPwd[64];
  4676. // WCHAR rgEncPwd[256]; (use with longest pwd above)
  4677. WCHAR rgDecPwd[32];
  4678. // WCHAR rgDecPwd[128]; (use with longest pwd above)
  4679. fRet = CfgUtilEncryptPassword(szPwd, ASIZE(rgEncPwd), rgEncPwd);
  4680. if (!fRet)
  4681. {
  4682. printf("CfgUtilEncryptPassword failed.\n");
  4683. goto end;
  4684. }
  4685. else
  4686. {
  4687. wprintf(L"Encrypted pwd = \"%ws\"\n", rgEncPwd);
  4688. }
  4689. fRet = CfgUtilDecryptPassword(rgEncPwd, ASIZE(rgDecPwd), rgDecPwd);
  4690. if (!fRet)
  4691. {
  4692. printf("CfgUtilDecryptPassword failed.\n");
  4693. goto end;
  4694. }
  4695. else
  4696. {
  4697. wprintf(L"Decrypted pwd = \"%ws\"\n", rgDecPwd);
  4698. }
  4699. end:
  4700. return;
  4701. }