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

3249 lines
119 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // File: netcfgconfig.cpp
  4. //
  5. // Module:
  6. //
  7. // Description: Implement class CNetcfgCluster and class CWlbsConfig
  8. //
  9. // Copyright (C) Microsoft Corporation. All rights reserved.
  10. //
  11. // Author: fengsun Created 3/2/00
  12. //
  13. //+----------------------------------------------------------------------------
  14. #include "pch.h"
  15. #pragma hdrstop
  16. #define ENABLE_PROFILE
  17. #include <winsock2.h>
  18. #include <windows.h>
  19. #include <clusapi.h>
  20. #include "debug.h"
  21. #include "netcon.h"
  22. #include "ncatlui.h"
  23. #include "ndispnp.h"
  24. #include "ncsetup.h"
  25. #include "netcfgn.h"
  26. #include "afilestr.h"
  27. #include "help.h"
  28. #include "resource.h"
  29. #include "ClusterDlg.h"
  30. #include "host.h"
  31. #include "ports.h"
  32. #include "wlbsparm.h"
  33. #include "wlbsconfig.h"
  34. #include "wlbscfg.h"
  35. #include <time.h>
  36. #include "netcfgcluster.h"
  37. #include "license.h"
  38. #include "tracelog.h"
  39. #include "utils.h"
  40. #include "netcfgconfig.tmh"
  41. #include "log_msgs.h"
  42. #define NETCFG_WLBS_ID L"ms_wlbs"
  43. // Used by Netsetup and Component's who's answer file references AdapterSections
  44. static const WCHAR c_szAdapterSections[] = L"AdapterSections";
  45. void WlbsToNetcfgConfig(const WlbsApiFuncs* pApiFuncs, const WLBS_REG_PARAMS* pWlbsConfig, NETCFG_WLBS_CONFIG* pBNetcfgConfig);
  46. void RemoveAllPortRules(PWLBS_REG_PARAMS reg_data);
  47. HRESULT ParamReadAnswerFile(CSetupInfFile& caf, PCWSTR answer_sections, WLBS_REG_PARAMS* paramp);
  48. bool WriteAdapterName(CWlbsConfig* pConfig, GUID& AdapterGuid);
  49. bool ValidateVipInRule(const PWCHAR pwszRuleString, const WCHAR pwToken, DWORD& dwVipLen);
  50. #if DBG
  51. static void TraceMsg(PCWSTR pszFormat, ...);
  52. #else
  53. #define TraceMsg NOP_FUNCTION
  54. #define DbgDumpBindPath NOP_FUNCTION
  55. #endif
  56. //
  57. // Function pointers to avoid link with wlbsctrl.dll
  58. //
  59. bool WINAPI ParamReadReg(const GUID& AdaperGuid, PWLBS_REG_PARAMS reg_data, bool fUpgradeFromWin2k = false, bool *pfPortRulesInBinaryForm = NULL);
  60. typedef bool (WINAPI* ParamReadRegFUNC)(const GUID& AdaperGuid, PWLBS_REG_PARAMS reg_data, bool fUpgradeFromWin2k = false, bool *pfPortRulesInBinaryForm = NULL);
  61. bool WINAPI ParamWriteReg(const GUID& AdaperGuid, PWLBS_REG_PARAMS reg_data);
  62. typedef bool (WINAPI* ParamWriteRegFUNC)(const GUID& AdaperGuid, PWLBS_REG_PARAMS reg_data);
  63. bool WINAPI ParamDeleteReg(const GUID& AdaperGuid, bool fDeleteObsoleteEntries = false);
  64. typedef bool (WINAPI* ParamDeleteRegFUNC)(const GUID& AdaperGuid, bool fDeleteObsoleteEntries = false);
  65. DWORD WINAPI ParamSetDefaults(PWLBS_REG_PARAMS reg_data);
  66. typedef DWORD (WINAPI* ParamSetDefaultsFUNC)(PWLBS_REG_PARAMS reg_data);
  67. bool WINAPI RegChangeNetworkAddress(const GUID& AdapterGuid, const WCHAR* mac_address, BOOL fRemove);
  68. typedef bool(WINAPI* RegChangeNetworkAddressFUNC) (const GUID& AdapterGuid, const WCHAR* mac_address, BOOL fRemove);
  69. void WINAPI NotifyAdapterAddressChange(const WCHAR* pszPnpDevNodeId);
  70. typedef void (WINAPI* NotifyAdapterAddressChangeFUNC)(const WCHAR* pszPnpDevNodeId);
  71. DWORD WINAPI WlbsAddPortRule(PWLBS_REG_PARAMS reg_data, PWLBS_PORT_RULE rule);
  72. typedef DWORD (WINAPI* WlbsAddPortRuleFUNC)(PWLBS_REG_PARAMS reg_data, PWLBS_PORT_RULE rule);
  73. DWORD WINAPI WlbsSetRemotePassword(PWLBS_REG_PARAMS reg_data, const WCHAR* password);
  74. typedef DWORD (WINAPI* WlbsSetRemotePasswordFUNC)(const PWLBS_REG_PARAMS reg_data, const WCHAR* password);
  75. DWORD WINAPI WlbsEnumPortRules(PWLBS_REG_PARAMS reg_data, PWLBS_PORT_RULE rules, PDWORD num_rules);
  76. typedef DWORD (WINAPI* WlbsEnumPortRulesFUNC)(PWLBS_REG_PARAMS reg_data, PWLBS_PORT_RULE rules, PDWORD num_rules);
  77. DWORD WINAPI NotifyDriverConfigChanges(HANDLE hDeviceWlbs, const GUID& AdapterGuid);
  78. typedef DWORD (WINAPI* NotifyDriverConfigChangesFUNC)(HANDLE hDeviceWlbs, const GUID& AdapterGuid);
  79. HKEY WINAPI RegOpenWlbsSetting(const GUID& AdapterGuid, bool fReadOnly);
  80. typedef HKEY (WINAPI* RegOpenWlbsSettingFUNC)(const GUID& AdapterGuid, bool fReadOnly);
  81. struct WlbsApiFuncs {
  82. ParamReadRegFUNC pfnParamReadReg;
  83. ParamWriteRegFUNC pfnParamWriteReg;
  84. ParamDeleteRegFUNC pfnParamDeleteReg;
  85. ParamSetDefaultsFUNC pfnParamSetDefaults;
  86. RegChangeNetworkAddressFUNC pfnRegChangeNetworkAddress;
  87. NotifyAdapterAddressChangeFUNC pfnNotifyAdapterAddressChange;
  88. WlbsAddPortRuleFUNC pfnWlbsAddPortRule;
  89. WlbsSetRemotePasswordFUNC pfnWlbsSetRemotePassword;
  90. WlbsEnumPortRulesFUNC pfnWlbsEnumPortRules;
  91. NotifyDriverConfigChangesFUNC pfnNotifyDriverConfigChanges;
  92. RegOpenWlbsSettingFUNC pfnRegOpenWlbsSetting;
  93. };
  94. //+----------------------------------------------------------------------------
  95. //
  96. // Function: LoadWlbsCtrlDll
  97. //
  98. // Description: Load wlbsctrl.dll and get all function pointers
  99. //
  100. // Arguments: WlbsApiFuncs* pFuncs -
  101. //
  102. // Returns: HINSTANCE - wlbsctrl.dll handle
  103. //
  104. // History: fengsun Created Header 3/2/00
  105. //
  106. //+----------------------------------------------------------------------------
  107. HINSTANCE LoadWlbsCtrlDll(WlbsApiFuncs* pFuncs) {
  108. TRACE_VERB("->%!FUNC!");
  109. TraceMsg(L"LoadWlbsCtrlDll");
  110. ASSERT(pFuncs);
  111. HINSTANCE hDll;
  112. DWORD dwStatus = 0;
  113. hDll = LoadLibrary(L"wlbsctrl.dll");
  114. if (hDll == NULL) {
  115. dwStatus = GetLastError();
  116. TraceError("Failed to load wlbsctrl.dll", dwStatus);
  117. TRACE_CRIT("%!FUNC! Could not load wlbsctrl.dll with %d", dwStatus);
  118. TRACE_VERB("<-%!FUNC!");
  119. return NULL;
  120. }
  121. pFuncs->pfnParamReadReg = (ParamReadRegFUNC)GetProcAddress(hDll, "ParamReadReg");
  122. pFuncs->pfnParamWriteReg = (ParamWriteRegFUNC)GetProcAddress(hDll, "ParamWriteReg");
  123. pFuncs->pfnParamDeleteReg = (ParamDeleteRegFUNC)GetProcAddress(hDll, "ParamDeleteReg");
  124. pFuncs->pfnParamSetDefaults = (ParamSetDefaultsFUNC)GetProcAddress(hDll, "ParamSetDefaults");
  125. pFuncs->pfnRegChangeNetworkAddress = (RegChangeNetworkAddressFUNC)GetProcAddress(hDll, "RegChangeNetworkAddress");
  126. pFuncs->pfnNotifyAdapterAddressChange = (NotifyAdapterAddressChangeFUNC)GetProcAddress(hDll, "NotifyAdapterAddressChange");
  127. pFuncs->pfnWlbsAddPortRule = (WlbsAddPortRuleFUNC)GetProcAddress(hDll, "WlbsAddPortRule");
  128. pFuncs->pfnWlbsSetRemotePassword = (WlbsSetRemotePasswordFUNC)GetProcAddress(hDll, "WlbsSetRemotePassword");
  129. pFuncs->pfnWlbsEnumPortRules = (WlbsEnumPortRulesFUNC)GetProcAddress(hDll, "WlbsEnumPortRules");
  130. pFuncs->pfnNotifyDriverConfigChanges = (NotifyDriverConfigChangesFUNC)GetProcAddress(hDll, "NotifyDriverConfigChanges");
  131. pFuncs->pfnRegOpenWlbsSetting = (RegOpenWlbsSettingFUNC)GetProcAddress(hDll, "RegOpenWlbsSetting");
  132. ASSERT (pFuncs->pfnParamReadReg != NULL);
  133. ASSERT (pFuncs->pfnParamWriteReg != NULL);
  134. ASSERT (pFuncs->pfnParamDeleteReg != NULL);
  135. ASSERT (pFuncs->pfnParamSetDefaults != NULL);
  136. ASSERT (pFuncs->pfnRegChangeNetworkAddress != NULL);
  137. ASSERT (pFuncs->pfnNotifyAdapterAddressChange != NULL);
  138. ASSERT (pFuncs->pfnWlbsAddPortRule != NULL);
  139. ASSERT (pFuncs->pfnWlbsSetRemotePassword != NULL);
  140. ASSERT (pFuncs->pfnWlbsEnumPortRules != NULL);
  141. ASSERT (pFuncs->pfnNotifyDriverConfigChanges != NULL);
  142. ASSERT (pFuncs->pfnRegOpenWlbsSetting != NULL);
  143. if (pFuncs->pfnParamReadReg == NULL ||
  144. pFuncs->pfnParamWriteReg == NULL||
  145. pFuncs->pfnParamDeleteReg == NULL||
  146. pFuncs->pfnParamSetDefaults == NULL||
  147. pFuncs->pfnRegChangeNetworkAddress == NULL||
  148. pFuncs->pfnNotifyAdapterAddressChange == NULL||
  149. pFuncs->pfnWlbsAddPortRule == NULL||
  150. pFuncs->pfnWlbsSetRemotePassword == NULL||
  151. pFuncs->pfnWlbsEnumPortRules == NULL||
  152. pFuncs->pfnNotifyDriverConfigChanges == NULL ||
  153. pFuncs->pfnRegOpenWlbsSetting == NULL) {
  154. dwStatus = GetLastError();
  155. TraceError("LoadWlbsCtrlDll GetProcAddress failed %d", dwStatus);
  156. TRACE_CRIT("%!FUNC! GetProcAddress failed %d", dwStatus);
  157. FreeLibrary(hDll);
  158. TRACE_VERB("<-%!FUNC!");
  159. return NULL;
  160. }
  161. TRACE_VERB("<-%!FUNC!");
  162. return hDll;
  163. }
  164. // Maximum characters in an IP address string of the form a.b.c.d
  165. const DWORD MAXIPSTRLEN = 20;
  166. void TransformOldPortRulesToNew(PWLBS_OLD_PORT_RULE p_old_port_rules,
  167. PWLBS_PORT_RULE p_new_port_rules,
  168. DWORD num_rules)
  169. {
  170. TRACE_VERB("->%!FUNC!");
  171. if (num_rules == 0)
  172. {
  173. TRACE_INFO("%!FUNC! No port rules");
  174. TRACE_VERB("<-%!FUNC!");
  175. return;
  176. }
  177. while(num_rules--)
  178. {
  179. lstrcpy(p_new_port_rules->virtual_ip_addr, CVY_DEF_ALL_VIP);
  180. p_new_port_rules->start_port = p_old_port_rules->start_port;
  181. p_new_port_rules->end_port = p_old_port_rules->end_port;
  182. #ifdef WLBSAPI_INTERNAL_ONLY
  183. p_new_port_rules->code = p_old_port_rules->code;
  184. #else
  185. p_new_port_rules->Private1 = p_old_port_rules->Private1;
  186. #endif
  187. p_new_port_rules->mode = p_old_port_rules->mode;
  188. p_new_port_rules->protocol = p_old_port_rules->protocol;
  189. #ifdef WLBSAPI_INTERNAL_ONLY
  190. p_new_port_rules->valid = p_old_port_rules->valid;
  191. #else
  192. p_new_port_rules->Private2 = p_old_port_rules->Private2;
  193. #endif
  194. switch (p_new_port_rules->mode)
  195. {
  196. case CVY_MULTI :
  197. p_new_port_rules->mode_data.multi.equal_load = p_old_port_rules->mode_data.multi.equal_load;
  198. p_new_port_rules->mode_data.multi.affinity = p_old_port_rules->mode_data.multi.affinity;
  199. p_new_port_rules->mode_data.multi.load = p_old_port_rules->mode_data.multi.load;
  200. break;
  201. case CVY_SINGLE :
  202. p_new_port_rules->mode_data.single.priority = p_old_port_rules->mode_data.single.priority;
  203. break;
  204. default:
  205. break;
  206. }
  207. p_old_port_rules++;
  208. p_new_port_rules++;
  209. }
  210. TRACE_VERB("<-%!FUNC!");
  211. return;
  212. }
  213. /* Initialize static data members of CNetcfgCluster */
  214. bool CNetcfgCluster::m_fMSCSWarningEventLatched = false;
  215. bool CNetcfgCluster::m_fMSCSWarningPopupLatched = false;
  216. //+----------------------------------------------------------------------------
  217. //
  218. // Function: CNetcfgCluster::CNetcfgCluster
  219. //
  220. // Description:
  221. //
  222. // Arguments: None
  223. //
  224. // Returns: Nothing
  225. //
  226. // History: fengsun Created Header 2/11/00
  227. //
  228. //+----------------------------------------------------------------------------
  229. CNetcfgCluster::CNetcfgCluster(CWlbsConfig* pConfig) {
  230. TRACE_VERB("->%!FUNC!");
  231. TraceMsg(L"CNetcfgCluster::CNetcfgCluster");
  232. m_fHasOriginalConfig = false;
  233. m_fMacAddrChanged = false;
  234. m_fReloadRequired = false;
  235. m_fRemoveAdapter = false;
  236. m_fOriginalBindingEnabled = false;
  237. m_fReenableAdapter = false;
  238. ZeroMemory(&m_AdapterGuid, sizeof(m_AdapterGuid));
  239. ASSERT(pConfig);
  240. m_pConfig = pConfig;
  241. TRACE_VERB("<-%!FUNC!");
  242. }
  243. //+----------------------------------------------------------------------------
  244. //
  245. // Function: CNetcfgCluster::~CNetcfgCluster
  246. //
  247. // Description:
  248. //
  249. // Arguments: None
  250. //
  251. // Returns: Nothing
  252. //
  253. // History: fengsun Created Header 2/11/00
  254. //
  255. //+----------------------------------------------------------------------------
  256. CNetcfgCluster::~CNetcfgCluster() {
  257. TRACE_VERB("<->%!FUNC!");
  258. TraceMsg(L"CNetcfgCluster::~CNetcfgCluster");
  259. }
  260. //+----------------------------------------------------------------------------
  261. //
  262. // Function: CNetcfgCluster::InitializeFromRegistry
  263. //
  264. // Description: Read the cluster settings from registry
  265. //
  266. // Arguments: const GUID& guidAdapter -
  267. //
  268. // Returns: DWORD - Win32 Error
  269. //
  270. // History: fengsun Created Header 2/13/00
  271. //
  272. //+----------------------------------------------------------------------------
  273. DWORD CNetcfgCluster::InitializeFromRegistry(const GUID& guidAdapter, bool fBindingEnabled, bool fUpgradeFromWin2k) {
  274. TRACE_VERB("->%!FUNC!");
  275. TraceMsg(L"CNetcfgCluster::InitializeFromRegistry");
  276. bool fPortRulesInBinaryForm = false;
  277. ASSERT(m_fHasOriginalConfig == false);
  278. m_fHasOriginalConfig = true;
  279. m_fOriginalBindingEnabled = fBindingEnabled;
  280. m_AdapterGuid = guidAdapter;
  281. if (!m_pConfig->m_pWlbsApiFuncs->pfnParamReadReg(m_AdapterGuid, &m_OriginalConfig, fUpgradeFromWin2k, &fPortRulesInBinaryForm))
  282. {
  283. TRACE_VERB("%!FUNC! error reading settings from the registry"); // This is verbose because this is invoked for non-NLB adapters too.
  284. TRACE_VERB("<-%!FUNC!");
  285. return ERROR_CANTREAD;
  286. }
  287. /* Force a write at apply. */
  288. if (fUpgradeFromWin2k || fPortRulesInBinaryForm)
  289. {
  290. m_fHasOriginalConfig = false;
  291. TRACE_INFO("%!FUNC! upgrading from win2k or port rules are in binary form");
  292. }
  293. CopyMemory(&m_CurrentConfig, &m_OriginalConfig, sizeof(m_CurrentConfig));
  294. TRACE_VERB("<-%!FUNC!");
  295. return ERROR_SUCCESS;
  296. }
  297. //+----------------------------------------------------------------------------
  298. //
  299. // Function: CNetcfgCluster::InitializeFromAnswerFile
  300. //
  301. // Description: Read cluster settings from answer file
  302. //
  303. // Arguments: PCWSTR answer_file -
  304. // PCWSTR answer_sections -
  305. //
  306. // Returns: DWORD -
  307. //
  308. // History: fengsun Created Header 2/13/00
  309. //
  310. //+----------------------------------------------------------------------------
  311. HRESULT CNetcfgCluster::InitializeFromAnswerFile(const GUID& AdapterGuid, CSetupInfFile& caf, PCWSTR answer_sections) {
  312. TRACE_VERB("->%!FUNC!");
  313. TraceMsg(L"CNetcfgCluster::InitializeFromAnswerFile");
  314. /* Setup with the default values first. */
  315. InitializeWithDefault(AdapterGuid);
  316. HRESULT hr = ParamReadAnswerFile(caf, answer_sections, &m_CurrentConfig);
  317. if (FAILED(hr)) {
  318. TRACE_CRIT("%!FUNC! failed CNetcfgCluster::ParamReadAnswerFile failed. returned: %d", hr);
  319. TraceError("CNetcfgCluster::InitializeFromAnswerFile failed at ParamReadAnswerFile", hr);
  320. }
  321. TRACE_VERB("<-%!FUNC!");
  322. return hr;
  323. }
  324. //+----------------------------------------------------------------------------
  325. //
  326. // Function: CNetcfgCluster::InitializeWithDefault
  327. //
  328. // Description: Set the cluster settings to default
  329. //
  330. // Arguments: None
  331. //
  332. // Returns: Nothing
  333. //
  334. // History: fengsun Created Header 2/13/00
  335. //
  336. //+----------------------------------------------------------------------------
  337. void CNetcfgCluster::InitializeWithDefault(const GUID& guidAdapter) {
  338. TRACE_VERB("->%!FUNC!");
  339. TraceMsg(L"CNetcfgCluster::InitializeWithDefault");
  340. time_t cur_time;
  341. ASSERT(m_fHasOriginalConfig == false);
  342. m_fHasOriginalConfig = false;
  343. m_pConfig->m_pWlbsApiFuncs->pfnParamSetDefaults(&m_CurrentConfig); // Always returns WLBS_OK
  344. m_CurrentConfig.install_date = time(& cur_time);
  345. // JosephJ 11/00 -- We used to call License_stamp to set this value,
  346. // but that was a holdover from convoy days.
  347. // We no longer use this field.
  348. //
  349. m_CurrentConfig.i_verify_date = 0;
  350. m_AdapterGuid = guidAdapter;
  351. TRACE_VERB("<-%!FUNC!");
  352. }
  353. //+----------------------------------------------------------------------------
  354. //
  355. // Function: CNetcfgCluster::SetConfig
  356. //
  357. // Description: SetConfig caches the settings without saving to registry
  358. // and can be retrieved by GetConfig.
  359. //
  360. // Arguments: const NETCFG_WLBS_CONFIG* pClusterConfig -
  361. //
  362. // Returns: Nothing
  363. //
  364. // History: fengsun Created Header 2/11/00
  365. //
  366. //+----------------------------------------------------------------------------
  367. void CNetcfgCluster::SetConfig(const NETCFG_WLBS_CONFIG* pClusterConfig) {
  368. TRACE_VERB("->%!FUNC!");
  369. TraceMsg(L"CNetcfgCluster::SetConfig");
  370. DWORD dwStatus = WLBS_OK; // Used for tracing output
  371. ASSERT(pClusterConfig != NULL);
  372. m_CurrentConfig.host_priority = pClusterConfig->dwHostPriority;
  373. m_CurrentConfig.rct_enabled = pClusterConfig->fRctEnabled ;
  374. m_CurrentConfig.cluster_mode = pClusterConfig->fJoinClusterOnBoot;
  375. m_CurrentConfig.mcast_support = pClusterConfig->fMcastSupport;
  376. m_CurrentConfig.fIGMPSupport = pClusterConfig->fIGMPSupport;
  377. m_CurrentConfig.fIpToMCastIp = pClusterConfig->fIpToMCastIp;
  378. lstrcpy(m_CurrentConfig.szMCastIpAddress, pClusterConfig->szMCastIpAddress);
  379. lstrcpy(m_CurrentConfig.cl_mac_addr, pClusterConfig->cl_mac_addr);
  380. lstrcpy(m_CurrentConfig.cl_ip_addr, pClusterConfig->cl_ip_addr);
  381. lstrcpy(m_CurrentConfig.cl_net_mask, pClusterConfig->cl_net_mask);
  382. lstrcpy(m_CurrentConfig.ded_ip_addr, pClusterConfig->ded_ip_addr);
  383. lstrcpy(m_CurrentConfig.ded_net_mask, pClusterConfig->ded_net_mask);
  384. lstrcpy(m_CurrentConfig.domain_name, pClusterConfig->domain_name);
  385. if (pClusterConfig->fChangePassword)
  386. {
  387. dwStatus = m_pConfig->m_pWlbsApiFuncs->pfnWlbsSetRemotePassword(&m_CurrentConfig, (WCHAR*)pClusterConfig->szPassword);
  388. if (WLBS_OK != dwStatus)
  389. {
  390. TRACE_CRIT("%!FUNC! set password failed with return code = %d", dwStatus);
  391. }
  392. }
  393. RemoveAllPortRules(&m_CurrentConfig);
  394. for (DWORD i=0; i<pClusterConfig->dwNumRules; i++) {
  395. WLBS_PORT_RULE PortRule;
  396. ZeroMemory(&PortRule, sizeof(PortRule));
  397. lstrcpy(PortRule.virtual_ip_addr, pClusterConfig->port_rules[i].virtual_ip_addr);
  398. PortRule.start_port = pClusterConfig->port_rules[i].start_port;
  399. PortRule.end_port = pClusterConfig->port_rules[i].end_port;
  400. PortRule.mode = pClusterConfig->port_rules[i].mode;
  401. PortRule.protocol = pClusterConfig->port_rules[i].protocol;
  402. if (PortRule.mode == WLBS_AFFINITY_SINGLE) {
  403. PortRule.mode_data.single.priority =
  404. pClusterConfig->port_rules[i].mode_data.single.priority;
  405. } else {
  406. PortRule.mode_data.multi.equal_load =
  407. pClusterConfig->port_rules[i].mode_data.multi.equal_load;
  408. PortRule.mode_data.multi.affinity =
  409. pClusterConfig->port_rules[i].mode_data.multi.affinity;
  410. PortRule.mode_data.multi.load =
  411. pClusterConfig->port_rules[i].mode_data.multi.load;
  412. }
  413. PortRule.valid = TRUE;
  414. CVY_RULE_CODE_SET(&PortRule);
  415. dwStatus = m_pConfig->m_pWlbsApiFuncs->pfnWlbsAddPortRule( &m_CurrentConfig, &PortRule );
  416. if (WLBS_OK != dwStatus)
  417. {
  418. TRACE_CRIT("%!FUNC! add port rule failed with return code = %d", dwStatus);
  419. }
  420. }
  421. TRACE_VERB("<-%!FUNC!");
  422. }
  423. //+----------------------------------------------------------------------------
  424. //
  425. // Function: CNetcfgCluster::GetConfig
  426. //
  427. // Description: Get the config, which could be cached by SetConfig call
  428. //
  429. // Arguments: NETCFG_WLBS_CONFIG* pClusterConfig -
  430. //
  431. // Returns: Nothing
  432. //
  433. // History: fengsun Created Header 2/11/00
  434. //
  435. //+----------------------------------------------------------------------------
  436. void CNetcfgCluster::GetConfig(NETCFG_WLBS_CONFIG* pClusterConfig) {
  437. TRACE_VERB("->%!FUNC!");
  438. TraceMsg(L"CNetcfgCluster::GetConfig");
  439. ASSERT(pClusterConfig != NULL);
  440. WlbsToNetcfgConfig(m_pConfig->m_pWlbsApiFuncs, &m_CurrentConfig, pClusterConfig);
  441. TRACE_VERB("<-%!FUNC!");
  442. }
  443. //+----------------------------------------------------------------------------
  444. //
  445. // Function: CNetcfgCluster::NotifyBindingChanges
  446. //
  447. // Description: Notify binding changes
  448. //
  449. // Arguments: DWORD dwChangeFlag -
  450. //
  451. // Returns: Nothing
  452. //
  453. // History: fengsun Created Header 2/13/00
  454. //
  455. //+----------------------------------------------------------------------------
  456. void CNetcfgCluster::NotifyBindingChanges(DWORD dwChangeFlag, INetCfgBindingPath* pncbp) {
  457. TRACE_VERB("->%!FUNC!");
  458. TraceMsg(L"CNetcfgCluster::NotifyBindingChanges");
  459. ASSERT(!(dwChangeFlag & NCN_ADD && dwChangeFlag & NCN_REMOVE));
  460. Assert(!(dwChangeFlag & NCN_ENABLE && dwChangeFlag & NCN_DISABLE));
  461. if (dwChangeFlag & NCN_ADD) { m_fRemoveAdapter = false; }
  462. if ((dwChangeFlag & NCN_ENABLE) && !m_fMSCSWarningPopupLatched)
  463. {
  464. /* Warn the user via a pop-up if we detect MSCS is installed, but allow the NLB install to proceed. */
  465. DWORD dwClusterState = 0;
  466. if (ERROR_SUCCESS == GetNodeClusterState(NULL, &dwClusterState))
  467. {
  468. if (ClusterStateNotRunning == dwClusterState || ClusterStateRunning == dwClusterState)
  469. {
  470. NcMsgBox(::GetActiveWindow(), IDS_PARM_WARN, IDS_PARM_MSCS_INSTALLED,
  471. MB_APPLMODAL | MB_ICONEXCLAMATION | MB_OK);
  472. m_fMSCSWarningPopupLatched = true;
  473. TRACE_INFO("%!FUNC! Cluster Service is installed");
  474. TraceMsg(L"CNetcfgCluster::NotifyBindingChanges Cluster Service is installed.");
  475. } else { /* MSCS is not installed. That's good! */ }
  476. } else {
  477. TRACE_CRIT("%!FUNC! error determining if MSCS is installed.");
  478. TraceMsg(L"CNetcfgCluster::NotifyBindingChanges error getting MSCS status.");
  479. }
  480. }
  481. if (dwChangeFlag & NCN_REMOVE) { m_fRemoveAdapter = true; }
  482. TRACE_VERB("<-%!FUNC!");
  483. }
  484. /*
  485. * Function: CNetcfgCluster::NotifyAdapter
  486. * Description: Notify an adapter of a state change
  487. * Author: shouse 6.1.00
  488. */
  489. DWORD CNetcfgCluster::NotifyAdapter (INetCfgComponent * pAdapter, DWORD newStatus) {
  490. TRACE_VERB("->%!FUNC!");
  491. HRESULT hr = S_OK;
  492. HDEVINFO hdi;
  493. SP_DEVINFO_DATA deid;
  494. PWSTR pszPnpDevNodeId;
  495. switch (newStatus) {
  496. case DICS_PROPCHANGE:
  497. TraceMsg(L"##### CWLBS::HrNotifyAdapter: Reload the adapter\n");
  498. break;
  499. case DICS_DISABLE:
  500. TraceMsg(L"##### CWLBS::HrNotifyAdapter: Disable the adapter\n");
  501. break;
  502. case DICS_ENABLE:
  503. TraceMsg(L"##### CWLBS::HrNotifyAdapter: Enable the adapter\n");
  504. break;
  505. default:
  506. TRACE_CRIT("%!FUNC! Invalid Notification 0x%x", newStatus);
  507. TraceMsg(L"##### CWLBS::HrNotifyAdapter: Invalid Notification 0x%x\n", newStatus);
  508. return ERROR_INVALID_PARAMETER;
  509. }
  510. if ((hr = HrSetupDiCreateDeviceInfoList(& GUID_DEVCLASS_NET, NULL, &hdi)) == S_OK) {
  511. if ((hr = pAdapter->GetPnpDevNodeId (& pszPnpDevNodeId)) == S_OK) {
  512. if ((hr = HrSetupDiOpenDeviceInfo (hdi, pszPnpDevNodeId, NULL, 0, &deid)) == S_OK) {
  513. if ((hr = HrSetupDiSendPropertyChangeNotification (hdi, & deid, newStatus, DICS_FLAG_GLOBAL, 0)) == S_OK) {
  514. TraceMsg(L"##### CWLBS::HrNotifyAdapter notified NIC\n");
  515. } else {
  516. TRACE_CRIT("%!FUNC! error %x in HrSetupDiSendPropertyChangeNotification", hr);
  517. TraceMsg(L"##### CWLBS::HrNotifyAdapter error %x in HrSetupDiSendPropertyChangeNotification\n", hr);
  518. }
  519. } else {
  520. TRACE_CRIT("%!FUNC! error %x in HrSetupDiOpenDeviceInfo", hr);
  521. TraceMsg(L"##### CWLBS::HrNotifyAdapter error %x in HrSetupDiOpenDeviceInfo\n", hr);
  522. }
  523. } else {
  524. TRACE_CRIT("%!FUNC! error %x in GetPnpDevNodeId", hr);
  525. TraceMsg(L"##### CWLBS::HrNotifyAdapter error %x in GetPnpDevNodeId\n", hr);
  526. }
  527. SetupDiDestroyDeviceInfoList (hdi);
  528. } else {
  529. TRACE_CRIT("%!FUNC! error %x in HrSetupDiCreateDeviceInfoList for Change: 0x%x", hr, newStatus);
  530. TraceMsg(L"##### CWLBS::HrNotifyAdapter error %x in HrSetupDiCreateDeviceInfoList for Change: 0x%x\n", newStatus);
  531. }
  532. TRACE_VERB("<-%!FUNC!");
  533. return hr;
  534. }
  535. //+----------------------------------------------------------------------------
  536. //
  537. // Function: CNetcfgCluster::ApplyRegistryChanges
  538. //
  539. // Description: Apply registry changes
  540. //
  541. // Arguments: None
  542. //
  543. // Returns: DWORD -
  544. //
  545. // History: fengsun Created Header 2/11/00
  546. //
  547. //+----------------------------------------------------------------------------
  548. DWORD CNetcfgCluster::ApplyRegistryChanges(bool fUninstall) {
  549. TRACE_VERB("->%!FUNC!");
  550. HRESULT hr = S_OK;
  551. DWORD dwStatus = 0;
  552. /* Uninstall WLBS or remove the adapter. */
  553. if (fUninstall || m_fRemoveAdapter) {
  554. if (m_fHasOriginalConfig &&m_OriginalConfig.mcast_support == false ) {
  555. /* If we were in unicast mode, remove the mac, and reload Nic driver upon PnP. */
  556. if (fUninstall) {
  557. INetCfgComponent * pAdapter = NULL;
  558. /* If the adapter is enabled, disable it when the MAC address changes. This prevents a
  559. switch from learning a MAC address due to ARPs that TCP/IP sends out before WLBS is
  560. enabled and able to spoof the source MAC. The NIC will be re-enabled in ApplyPnpChanges(). */
  561. if ((hr = GetAdapterFromGuid(m_pConfig->m_pNetCfg, m_AdapterGuid, &pAdapter)) == S_OK) {
  562. ULONG status = 0UL;
  563. /* Only disable the adapter if the adapter is currently enabled and NLB was initially
  564. (in this netcfg session) bound to the adapter. */
  565. if (m_fOriginalBindingEnabled) {
  566. if ((hr = pAdapter->GetDeviceStatus(&status)) == S_OK) {
  567. if (status != CM_PROB_DISABLED) {
  568. m_fReenableAdapter = true;
  569. NotifyAdapter(pAdapter, DICS_DISABLE);
  570. }
  571. }
  572. }
  573. pAdapter->Release();
  574. pAdapter = NULL;
  575. }
  576. m_fMacAddrChanged = true;
  577. }
  578. /* remove mac addr, */
  579. if (m_pConfig->m_pWlbsApiFuncs->pfnRegChangeNetworkAddress(m_AdapterGuid, m_OriginalConfig.cl_mac_addr, true) == false) {
  580. dwStatus = GetLastError();
  581. TraceError("CWlbsCluster::WriteConfig failed at RegChangeNetworkAddress", dwStatus);
  582. TRACE_CRIT("<-%!FUNC! failed removing MAC address with %d", dwStatus);
  583. }
  584. }
  585. m_pConfig->m_pWlbsApiFuncs->pfnParamDeleteReg(m_AdapterGuid);
  586. TRACE_INFO("<-%!FUNC! Exiting on success removing adapter or uninstalling NLB");
  587. TRACE_VERB("<-%!FUNC!");
  588. return ERROR_SUCCESS;
  589. }
  590. /* Find out whether the adapter is bound to NLB. */
  591. INetCfgComponent* pAdapter = NULL;
  592. bool fCurrentBindingEnabled;
  593. bool fOriginalMacAddrSet; bool fCurrentMacAddrSet;
  594. if ((hr = GetAdapterFromGuid(m_pConfig->m_pNetCfg, m_AdapterGuid, &pAdapter)) != S_OK) {
  595. fCurrentBindingEnabled = false;
  596. } else {
  597. fCurrentBindingEnabled = (m_pConfig->IsBoundTo(pAdapter) == S_OK);
  598. pAdapter->Release();
  599. pAdapter = NULL;
  600. }
  601. if ((m_fOriginalBindingEnabled == fCurrentBindingEnabled) && m_fHasOriginalConfig) {
  602. if (!memcmp(&m_OriginalConfig, &m_CurrentConfig, sizeof(m_CurrentConfig))) {
  603. /* If the binding hasn't changed and we have previously bound to this adapter
  604. (originalconfig -> loaded from registry) and the NLB parameters haven't
  605. changed, then nothing changed and we can bail out here. */
  606. LOG_INFO("CNetcfgCluster::ApplyRegistryChanges, Exiting !!!");
  607. TRACE_INFO("%!FUNC! no changes needed...exiting");
  608. TRACE_VERB("<-%!FUNC!");
  609. return WLBS_OK;
  610. } else {
  611. /* Otherwise, if the binding hasn't changed, NLB is currently bound, and we have
  612. previously bound to this adapter (originalconfig -> loaded from registry)
  613. and the NLB parameters HAVE changed, then we need to reload the driver. */
  614. if (fCurrentBindingEnabled) m_fReloadRequired = true;
  615. }
  616. }
  617. /* If MSCS is installed and NLB is bound, throw an NT event (event is latched, so check this too) */
  618. DWORD dwClusterState = 0;
  619. if (fCurrentBindingEnabled && !m_fMSCSWarningEventLatched)
  620. {
  621. if (ERROR_SUCCESS == GetNodeClusterState(NULL, &dwClusterState))
  622. {
  623. if (ClusterStateNotRunning == dwClusterState || ClusterStateRunning == dwClusterState)
  624. {
  625. /* Log NT event -- Do not throw an error if these calls fail. This is just best effort. */
  626. HANDLE hES = RegisterEventSourceW (NULL, CVY_NAME);
  627. if (NULL != hES)
  628. {
  629. TRACE_INFO("%!FUNC! detected that MSCS is installed");
  630. TraceMsg(L"CNetcfgCluster::ApplyRegistryChanges MSCS warning event needs to be logged.");
  631. if (ReportEventW(hES, /* Handle to event log*/
  632. EVENTLOG_WARNING_TYPE, /* Event type */
  633. 0, /* Category */
  634. IDS_INSTALL_WITH_MSCS_INSTALLED, /* MessageId */
  635. NULL, /* Security identifier */
  636. 0, /* Num args to event string */
  637. 0, /* Size of binary data */
  638. NULL, /* Ptr to args for event string */
  639. NULL)) /* Ptr to binary data */
  640. {
  641. /* Latch the event, so it won't be thrown again */
  642. m_fMSCSWarningEventLatched = true;
  643. }
  644. else
  645. {
  646. /* Couldn't log the NT event. Don't fail anything; we aren't latched so we'll try to log again on next change */
  647. TRACE_CRIT("%!FUNC! call to write the MSCS warning event failed");
  648. TraceMsg(L"CNetcfgCluster::ApplyRegistryChanges failed to write MSCS warning event to log.");
  649. }
  650. DeregisterEventSource(hES);
  651. }
  652. else
  653. {
  654. TRACE_CRIT("%!FUNC! failed call to RegisterEventSource to log the MSCS warning event.");
  655. TraceMsg(L"CNetcfgCluster::ApplyRegistryChanges failed call to RegisterEventSource for MSCS warning event.");
  656. }
  657. }
  658. else { /* MS Cluster Service is not installed. That's good! */ }
  659. }
  660. else
  661. {
  662. TRACE_CRIT("%!FUNC! error determining if MSCS is installed.");
  663. TraceMsg(L"CNetcfgCluster::ApplyRegistryChanges error checking MSCS state.");
  664. }
  665. }
  666. // The m_fHasOriginalConfig flag will be false if
  667. // 1. Bind NLB for the first time
  668. // 2. Clean Installs with NLB info in Answer file
  669. // 3. Upgrade from NT 4 or Win 2k or XP with Port Rules in Binary format
  670. // In case #1 & #2, the following attempt to delete registry entries from the old location
  671. // will be a no-op 'cos there will be no old registry entries to delete
  672. bool bStatus = true;
  673. if (!m_fHasOriginalConfig)
  674. {
  675. if (!m_pConfig->m_pWlbsApiFuncs->pfnParamDeleteReg(m_AdapterGuid, true))
  676. {
  677. TRACE_CRIT("%!FUNC! error deleting parameters from the registry");
  678. }
  679. }
  680. if (!m_pConfig->m_pWlbsApiFuncs->pfnParamWriteReg(m_AdapterGuid, &m_CurrentConfig))
  681. {
  682. TRACE_CRIT("%!FUNC! error writing parameters into the registry");
  683. TRACE_VERB("<-%!FUNC!");
  684. return WLBS_REG_ERROR;
  685. }
  686. /* Write adapter name into the registry for API use. */
  687. if(!WriteAdapterName(m_pConfig, m_AdapterGuid))
  688. {
  689. TRACE_CRIT("%!FUNC! error writing adapter name into the registry (for API use)");
  690. }
  691. /* Figure out whether we need to change MAC address. */
  692. if (!m_fOriginalBindingEnabled || !m_fHasOriginalConfig)
  693. fOriginalMacAddrSet = false;
  694. else
  695. fOriginalMacAddrSet = !m_OriginalConfig.mcast_support;
  696. if (!fCurrentBindingEnabled)
  697. fCurrentMacAddrSet = false;
  698. else
  699. fCurrentMacAddrSet = !m_CurrentConfig.mcast_support;
  700. /* If the MAC address changes for any reason, disable/enable the adapter. */
  701. if ((fOriginalMacAddrSet != fCurrentMacAddrSet) || wcscmp(m_CurrentConfig.cl_mac_addr, m_OriginalConfig.cl_mac_addr))
  702. {
  703. INetCfgComponent * pAdapter = NULL;
  704. /* If the adapter is enabled, disable it when the MAC address changes. This prevents a
  705. switch from learning a MAC address due to ARPs that TCP/IP sends out before WLBS is
  706. enabled and able to spoof the source MAC. The NIC will be re-enabled in ApplyPnpChanges(). */
  707. if ((hr = GetAdapterFromGuid(m_pConfig->m_pNetCfg, m_AdapterGuid, &pAdapter)) == S_OK) {
  708. ULONG status = 0UL;
  709. if ((hr = pAdapter->GetDeviceStatus(&status)) == S_OK) {
  710. if (status != CM_PROB_DISABLED) {
  711. m_fReenableAdapter = true;
  712. m_fReloadRequired = false; /* If we are disabling/enabling the adapter, we don't need to reload too. */
  713. LOG_INFO("CNetcfgCluster::ApplyRegistryChanges, About to Disable Adapter");
  714. dwStatus = NotifyAdapter(pAdapter, DICS_DISABLE);
  715. LOG_INFO("CNetcfgCluster::ApplyRegistryChanges, Returned from Disabling Adapter");
  716. if (!SUCCEEDED(dwStatus))
  717. {
  718. TRACE_CRIT("%!FUNC! a call to NotifyAdapter to disable the adapter for a MAC address change failed with %d", dwStatus);
  719. } else
  720. {
  721. TRACE_INFO("%!FUNC! a call to NotifyAdapter to disable the adapter for a MAC address change succeeded");
  722. }
  723. }
  724. }
  725. pAdapter->Release();
  726. pAdapter = NULL;
  727. }
  728. /* Change the mac address. */
  729. m_fMacAddrChanged = true;
  730. m_pConfig->m_pWlbsApiFuncs->pfnRegChangeNetworkAddress(m_AdapterGuid, m_CurrentConfig.cl_mac_addr, !fCurrentMacAddrSet);
  731. TraceMsg(L"New MAC address written to registry");
  732. TRACE_INFO("%!FUNC! new MAC address written to registry");
  733. }
  734. CopyMemory(&m_OriginalConfig, &m_CurrentConfig, sizeof(m_CurrentConfig));
  735. m_fHasOriginalConfig = true;
  736. m_fOriginalBindingEnabled = fCurrentBindingEnabled;
  737. TRACE_VERB("<-%!FUNC!");
  738. return ERROR_SUCCESS;
  739. }
  740. //+----------------------------------------------------------------------------
  741. //
  742. // Function: CNetcfgCluster::ResetMSCSLatches
  743. //
  744. // Description: Resets the static flags for latching warning popup and NT event
  745. // when MSCS is already installed. This reset allows the user to
  746. // control the period during which latching is valid
  747. //
  748. // Arguments: None
  749. //
  750. // Returns: None
  751. //
  752. // History: chrisdar Created: 01.05.07
  753. //
  754. //+----------------------------------------------------------------------------
  755. void CNetcfgCluster::ResetMSCSLatches() {
  756. TRACE_VERB("->%!FUNC!");
  757. CNetcfgCluster::m_fMSCSWarningEventLatched = false;
  758. CNetcfgCluster::m_fMSCSWarningPopupLatched = false;
  759. TRACE_VERB("<-%!FUNC!");
  760. }
  761. //+----------------------------------------------------------------------------
  762. //
  763. // Function: CNetcfgCluster::ApplyPnpChanges
  764. //
  765. // Description: Apply the changes to drivers
  766. //
  767. // Arguments: HANDLE hWlbsDevice -
  768. //
  769. // Returns: DWORD - Win32 Error
  770. //
  771. // History: fengsun Created Header 2/11/00
  772. //
  773. //+----------------------------------------------------------------------------
  774. DWORD CNetcfgCluster::ApplyPnpChanges(HANDLE hDeviceWlbs) {
  775. TRACE_VERB("->%!FUNC!");
  776. if (m_fReloadRequired && (hDeviceWlbs != INVALID_HANDLE_VALUE)) {
  777. DWORD dwStatus = m_pConfig->m_pWlbsApiFuncs->pfnNotifyDriverConfigChanges(hDeviceWlbs, m_AdapterGuid); // Always returns ERROR_SUCCESS
  778. TraceMsg(L"NLB driver notified of configuration changes");
  779. TRACE_INFO("%!FUNC! nlb driver notified of configuration changes and returned %d where %d indicates success", dwStatus, ERROR_SUCCESS);
  780. }
  781. if (m_fMacAddrChanged) {
  782. PWSTR pszPnpDevNodeId = NULL;
  783. INetCfgComponent* pAdapter = NULL;
  784. HRESULT hr;
  785. hr = GetAdapterFromGuid(m_pConfig->m_pNetCfg, m_AdapterGuid, &pAdapter);
  786. if (hr != S_OK) {
  787. TraceError("GetAdapterFromGuid failed at GetPnpDevNodeId", hr);
  788. TRACE_CRIT("%!FUNC! call to GetAdapterFromGuid failed with %d", hr);
  789. return false;
  790. }
  791. hr = pAdapter->GetPnpDevNodeId (& pszPnpDevNodeId);
  792. if (hr != S_OK) {
  793. TraceError("HrWriteAdapterName failed at GetPnpDevNodeId", hr);
  794. TRACE_CRIT("%!FUNC! call to GetPnpDevNodeId failed with %d", hr);
  795. return false;
  796. }
  797. m_pConfig->m_pWlbsApiFuncs->pfnNotifyAdapterAddressChange(pszPnpDevNodeId); // No return value to check
  798. TraceMsg(L"Adapter notified of new MAC address");
  799. TRACE_INFO("%!FUNC! adapter notified of new MAC address");
  800. /* If the adapter was disabled in ApplyRegistryChanges() because the MAC
  801. address changed and the NIC was enabled, then re-enable it here. */
  802. if (m_fReenableAdapter) {
  803. LOG_INFO("CNetcfgCluster::ApplyPnpChanges, About to Enable Adapter");
  804. DWORD dwStatus = NotifyAdapter(pAdapter, DICS_ENABLE);
  805. LOG_INFO("CNetcfgCluster::ApplyPnpChanges, Returned from Enabling Adapter");
  806. if (!SUCCEEDED(dwStatus))
  807. {
  808. TRACE_CRIT("%!FUNC! a call to NotifyAdapter to reenable the adapter after a previous disable for a MAC address change failed with %d", dwStatus);
  809. } else
  810. {
  811. TRACE_INFO("%!FUNC! a call to NotifyAdapter to reenable the adapter after a previous disable for a MAC address change succeeded");
  812. }
  813. }
  814. pAdapter->Release();
  815. pAdapter = NULL;
  816. CoTaskMemFree(pszPnpDevNodeId);
  817. }
  818. TRACE_VERB("<-%!FUNC!");
  819. return ERROR_SUCCESS;
  820. }
  821. /*
  822. * Function: CNetcfgCluster::CheckForDuplicateClusterIPAddress
  823. * Description: Used to check for duplicate cluster IP addresses across multiple NICs.
  824. * Author: shouse 10.24.00
  825. */
  826. bool CNetcfgCluster::CheckForDuplicateClusterIPAddress (WCHAR * szOtherIP) {
  827. TRACE_VERB("->%!FUNC!");
  828. TraceMsg(L"CNetcfgCluster::CheckForDuplicateClusterIPAddress");
  829. HRESULT hr = S_OK;
  830. /* First check to see whether the cluster IP addresses match. */
  831. if (!wcscmp(m_CurrentConfig.cl_ip_addr, szOtherIP)) {
  832. INetCfgComponent* pAdapter = NULL;
  833. /* If they do match, get the INetCfgComponent interface for this GUID. */
  834. if ((hr = GetAdapterFromGuid(m_pConfig->m_pNetCfg, m_AdapterGuid, &pAdapter)) != S_OK) {
  835. TraceError("GetAdapterFromGuid failed in CNetcfgCluster::CheckForDuplicateClusterIPAddress", hr);
  836. TRACE_CRIT("%!FUNC! call to GetAdapterFromGuid failed with %d", hr);
  837. TRACE_VERB("<-%!FUNC!");
  838. return FALSE;
  839. }
  840. /* If NLB is bound to this adapter, then there is a conflict. */
  841. if (m_pConfig->IsBoundTo(pAdapter) == S_OK)
  842. {
  843. TRACE_INFO("%!FUNC! duplicate IP address found");
  844. TRACE_VERB("<-%!FUNC!");
  845. return TRUE;
  846. }
  847. }
  848. TRACE_INFO("%!FUNC! no duplicate IP address was found");
  849. TRACE_VERB("<-%!FUNC!");
  850. return FALSE;
  851. }
  852. // ----------------------------------------------------------------------
  853. //
  854. // Function: CWlbsConfig::CWlbsConfig
  855. //
  856. // Purpose: constructor for class CWlbsConfig
  857. //
  858. // Arguments: None
  859. //
  860. // Returns: None
  861. //
  862. // Notes:
  863. //
  864. // ----------------------------------------------------------------------
  865. CWlbsConfig::CWlbsConfig(VOID) {
  866. TRACE_VERB("->%!FUNC!");
  867. TraceMsg(L"CWlbsConfig::CWlbsConfig");
  868. m_pWlbsComponent = NULL;
  869. m_pNetCfg = NULL;
  870. m_ServiceOperation = WLBS_SERVICE_NONE;
  871. m_hDeviceWlbs = INVALID_HANDLE_VALUE;
  872. m_hdllWlbsCtrl = NULL;
  873. m_pWlbsApiFuncs = NULL;
  874. /* Initialize latched flags of CNetCfgCluster so that we get pristine
  875. MSCS popup and NT events when making config changes and MSCS is installed.
  876. Comment out this call if the NT event and popup should be thrown only
  877. once per loading of this dll */
  878. CNetcfgCluster::ResetMSCSLatches();
  879. TRACE_VERB("<-%!FUNC!");
  880. }
  881. // ----------------------------------------------------------------------
  882. //
  883. // Function: CWlbsConfig::~CWlbsConfig
  884. //
  885. // Purpose: destructor for class CWlbsConfig
  886. //
  887. // Arguments: None
  888. //
  889. // Returns: None
  890. //
  891. // Notes:
  892. //
  893. // ----------------------------------------------------------------------
  894. CWlbsConfig::~CWlbsConfig(VOID) {
  895. TRACE_VERB("->%!FUNC!");
  896. TraceMsg(L"CWlbsConfig::~CWlbsConfig");
  897. /* Release interfaces if acquired. */
  898. ReleaseObj(m_pWlbsComponent);
  899. ReleaseObj(m_pNetCfg);
  900. if (m_pWlbsApiFuncs) delete m_pWlbsApiFuncs;
  901. if (m_hdllWlbsCtrl) FreeLibrary(m_hdllWlbsCtrl);
  902. /* Free all clusters. */
  903. for (vector<CNetcfgCluster*>::iterator iter = m_vtrCluster.begin(); iter != m_vtrCluster.end(); iter++) {
  904. CNetcfgCluster* pCluster = *iter;
  905. ASSERT(pCluster != NULL);
  906. delete pCluster;
  907. }
  908. TRACE_VERB("<-%!FUNC!");
  909. }
  910. // ----------------------------------------------------------------------
  911. //
  912. // Function: CWlbsConfig::Initialize
  913. //
  914. // Purpose: Initialize the notify object
  915. //
  916. // Arguments:
  917. // pnccItem [in] pointer to INetCfgComponent object
  918. // pnc [in] pointer to INetCfg object
  919. // fInstalling [in] TRUE if we are being installed
  920. //
  921. // Returns:
  922. //
  923. // Notes:
  924. //
  925. // ----------------------------------------------------------------------
  926. STDMETHODIMP CWlbsConfig::Initialize(INetCfg* pNetCfg, BOOL fInstalling) {
  927. TRACE_VERB("->%!FUNC!");
  928. TraceMsg(L"CWlbsConfig::Initialize");
  929. HRESULT hr = S_OK;
  930. /* Load wlbsctrl.dll */
  931. ASSERT(m_pWlbsApiFuncs == NULL);
  932. ASSERT(m_hdllWlbsCtrl == NULL);
  933. m_pWlbsApiFuncs = new WlbsApiFuncs;
  934. if (m_pWlbsApiFuncs == NULL)
  935. {
  936. TRACE_CRIT("%!FUNC! memory allocation failed for m_pWlbsApiFuncs");
  937. return E_OUTOFMEMORY;
  938. }
  939. m_hdllWlbsCtrl = LoadWlbsCtrlDll(m_pWlbsApiFuncs);
  940. if (m_hdllWlbsCtrl == NULL) {
  941. DWORD dwStatus = GetLastError();
  942. TRACE_CRIT("%!FUNC! failed to load wlbsctrl.dll with error %d", dwStatus);
  943. TraceError("CWlbsConfig::Initialize Failed to load wlbsctrl.dll", dwStatus);
  944. // CLD: What in the world is going on here?
  945. if (dwStatus == ERROR_SUCCESS)
  946. {
  947. TRACE_VERB("<-%!FUNC!");
  948. return E_FAIL;
  949. }
  950. TRACE_VERB("<-%!FUNC!");
  951. return HRESULT_FROM_WIN32(dwStatus);
  952. }
  953. AddRefObj (m_pNetCfg = pNetCfg);
  954. /* Find the WLBS component. */
  955. ASSERT(m_pWlbsComponent == NULL);
  956. m_pWlbsComponent = NULL;
  957. /* The WLBS conponent object is not available at installation time. */
  958. if (!fInstalling) {
  959. if (FAILED(hr = pNetCfg->FindComponent(NETCFG_WLBS_ID, &m_pWlbsComponent)) || m_pWlbsComponent == NULL) {
  960. ASSERT(fInstalling);
  961. TRACE_CRIT("%!FUNC! find for nlb component object failed with %d", hr);
  962. TraceError("INetCfg::FindComponent failed",hr);
  963. }
  964. hr = LoadAllAdapterSettings(false); // fUpgradeFromWin2k = false
  965. if (FAILED(hr))
  966. {
  967. TRACE_CRIT("%!FUNC! loading all adapter settings for a non-window 2000 upgrade failed with %d", hr);
  968. }
  969. }
  970. ASSERT_VALID(this);
  971. TRACE_VERB("<-%!FUNC!");
  972. return S_OK;
  973. }
  974. //+----------------------------------------------------------------------------
  975. //
  976. // Function: CWlbsConfig::LoadAllAdapters
  977. //
  978. // Description: Load all cluster settings from registry
  979. //
  980. // Arguments: None
  981. //
  982. // Returns: HRESULT -
  983. //
  984. // History: fengsun Created Header 2/14/00
  985. //
  986. //+----------------------------------------------------------------------------
  987. HRESULT CWlbsConfig::LoadAllAdapterSettings(bool fUpgradeFromWin2k) {
  988. TRACE_VERB("->%!FUNC!");
  989. TraceMsg(L"CWlbsConfig::LoadAllAdapterSettings");
  990. HRESULT hr = S_OK;
  991. INetCfgClass *pNetCfgClass = NULL;
  992. INetCfgComponent* pNetCardComponent = NULL;
  993. ASSERT_VALID(this);
  994. hr = m_pNetCfg->QueryNetCfgClass(&GUID_DEVCLASS_NET, IID_INetCfgClass, (void **)&pNetCfgClass);
  995. if (FAILED(hr)) {
  996. TraceError("INetCfg::QueryNetCfgClass failed", hr);
  997. TRACE_CRIT("%!FUNC! call to QueryNetCfgClass failed with %d", hr);
  998. TRACE_VERB("<-%!FUNC!");
  999. return hr;
  1000. }
  1001. /* Get an enumerator to list all network devices. */
  1002. IEnumNetCfgComponent *pIEnumComponents = NULL;
  1003. if (FAILED(hr = pNetCfgClass->EnumComponents(&pIEnumComponents))) {
  1004. TraceError("INetCfg::EnumComponents failed", hr);
  1005. TRACE_CRIT("%!FUNC! call to enumerate components failed with %d", hr);
  1006. pNetCfgClass->Release();
  1007. TRACE_VERB("<-%!FUNC!");
  1008. return hr;
  1009. }
  1010. /* Go through all the adapters and load settings for adapters that are bound to WLBS. */
  1011. while (pIEnumComponents->Next(1, &pNetCardComponent, NULL) == S_OK) {
  1012. GUID AdapterGuid;
  1013. /* Retrieve the instance GUID of the component. */
  1014. if (FAILED(hr = (pNetCardComponent)->GetInstanceGuid(&AdapterGuid))) {
  1015. pNetCardComponent->Release();
  1016. pNetCardComponent = NULL;
  1017. TraceError("GetInstanceGuid failed", hr);
  1018. TRACE_CRIT("%!FUNC! call to retrieve the guid instance of the adapter failed with %d", hr);
  1019. continue;
  1020. }
  1021. bool fBound = (IsBoundTo(pNetCardComponent) == S_OK);
  1022. pNetCardComponent->Release();
  1023. pNetCardComponent = NULL;
  1024. /* Win2k support only one adapter. The settings will be lost if not bound. */
  1025. if (fUpgradeFromWin2k && !fBound) continue;
  1026. /* Load settings regardless of bindings for non-upgrade case. */
  1027. CNetcfgCluster* pCluster = new CNetcfgCluster(this);
  1028. if (pCluster == NULL)
  1029. {
  1030. TRACE_CRIT("%!FUNC! failed memory allocation for CNetcfgCluster");
  1031. TRACE_VERB("<-%!FUNC!");
  1032. return ERROR_OUTOFMEMORY;
  1033. }
  1034. DWORD dwStatus = pCluster->InitializeFromRegistry(AdapterGuid, fBound, fUpgradeFromWin2k);
  1035. if (dwStatus != ERROR_SUCCESS) {
  1036. /* If NLB is already bound to this adapter, this is an issue - if not, its fine. */
  1037. if (fBound) {
  1038. TRACE_CRIT("%!FUNC! reading nlb information from registry failed with %d", dwStatus);
  1039. ASSERT(!fBound);
  1040. }
  1041. delete pCluster;
  1042. continue;
  1043. }
  1044. m_vtrCluster.push_back(pCluster);
  1045. }
  1046. pIEnumComponents->Release();
  1047. pNetCfgClass->Release();
  1048. TRACE_VERB("<-%!FUNC!");
  1049. return S_OK;
  1050. }
  1051. // ----------------------------------------------------------------------
  1052. //
  1053. // Function: CWlbsConfig::ReadAnswerFile
  1054. //
  1055. // Purpose: Read settings from answerfile and configure WLBS
  1056. //
  1057. // Arguments:
  1058. // pszAnswerFile [in] name of AnswerFile
  1059. // pszAnswerSection [in] name of parameters section
  1060. //
  1061. // Returns:
  1062. //
  1063. // Notes: Dont do anything irreversible (like modifying registry) yet
  1064. // since the config. actually complete only when Apply is called!
  1065. //
  1066. // ----------------------------------------------------------------------
  1067. STDMETHODIMP CWlbsConfig::ReadAnswerFile(PCWSTR pszAnswerFile, PCWSTR pszAnswerSection) {
  1068. TRACE_VERB("->%!FUNC!");
  1069. TraceMsg(L"CWlbsConfig::ReadAnswerFile");
  1070. HRESULT hr = S_OK;
  1071. CSetupInfFile caf;
  1072. ASSERT_VALID(this);
  1073. AssertSz(pszAnswerFile, "Answer file string is NULL!");
  1074. AssertSz(pszAnswerSection, "Answer file sections string is NULL!");
  1075. // Open the answer file.
  1076. hr = caf.HrOpen(pszAnswerFile, NULL, INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL);
  1077. if (FAILED(hr)) {
  1078. TraceError("caf.HrOpen failed", hr);
  1079. TRACE_CRIT("%!FUNC! attempt to open answer file failed with %d", hr);
  1080. TRACE_VERB("<-%!FUNC!");
  1081. return S_OK;
  1082. }
  1083. // Get the adapter specific parameters
  1084. WCHAR * mszAdapterList;
  1085. hr = HrSetupGetFirstMultiSzFieldWithAlloc(caf.Hinf(), pszAnswerSection, c_szAdapterSections, &mszAdapterList);
  1086. if (FAILED(hr)) {
  1087. TraceError("WLBS HrSetupGetFirstMultiSzFieldWithAlloc failed", hr);
  1088. TRACE_CRIT("%!FUNC! attempt to retrieve adapter list from answer file failed with %d", hr);
  1089. TRACE_VERB("<-%!FUNC!");
  1090. return S_OK;
  1091. }
  1092. tstring strAdapterName;
  1093. tstring strInterfaceRegPath;
  1094. for (PCWSTR pszAdapterSection = mszAdapterList; *pszAdapterSection; pszAdapterSection += lstrlenW(pszAdapterSection) + 1) {
  1095. // Get the card name "SpecificTo = ..."
  1096. hr = HrSetupGetFirstString(caf.Hinf(), pszAdapterSection, c_szAfSpecificTo, &strAdapterName);
  1097. if (FAILED(hr)) {
  1098. TraceError("WLBS HrSetupGetFirstString failed", hr);
  1099. TRACE_CRIT("%!FUNC! attempt to retrieve adapter name from answer file failed with %d. Skipping to next adapter", hr);
  1100. continue;
  1101. }
  1102. GUID guidNetCard;
  1103. if (!FGetInstanceGuidOfComponentInAnswerFile(strAdapterName.c_str(), m_pNetCfg, &guidNetCard)) {
  1104. TraceError("WLBS FGetInstanceGuidOfComponentInAnswerFile failed", FALSE);
  1105. TRACE_CRIT("%!FUNC! attempt to retrieve netcard guid from answer file failed. Skipping to next adapter");
  1106. continue;
  1107. }
  1108. CNetcfgCluster* pCluster = new CNetcfgCluster(this);
  1109. if (pCluster == NULL)
  1110. {
  1111. TRACE_CRIT("%!FUNC! memory allocation failure for CNetcfgCluster");
  1112. TRACE_VERB("<-%!FUNC!");
  1113. return ERROR_OUTOFMEMORY;
  1114. }
  1115. if (FAILED(hr = pCluster->InitializeFromAnswerFile(guidNetCard, caf, pszAdapterSection))) {
  1116. TraceError("WLBS InitializeFromAnswerFile failed", hr);
  1117. TRACE_CRIT("%!FUNC! attempt to initialize the adapter settings from answer file failed with %d. Skipping to next adapter", hr);
  1118. delete pCluster;
  1119. continue;
  1120. }
  1121. m_vtrCluster.push_back(pCluster);
  1122. }
  1123. delete [] mszAdapterList;
  1124. caf.Close();
  1125. TRACE_VERB("<-%!FUNC!");
  1126. return S_OK;
  1127. }
  1128. // ----------------------------------------------------------------------
  1129. //
  1130. // Function: CWlbsConfig::Install
  1131. //
  1132. // Purpose: Do operations necessary for install.
  1133. //
  1134. // Arguments:
  1135. // dwSetupFlags [in] Setup flags
  1136. //
  1137. // Returns: S_OK on success, otherwise an error code
  1138. //
  1139. // Notes: Dont do anything irreversible (like modifying registry) yet
  1140. // since the config. actually complete only when Apply is called!
  1141. //
  1142. // ----------------------------------------------------------------------
  1143. STDMETHODIMP CWlbsConfig::Install(DWORD /* dw */) {
  1144. TRACE_VERB("->%!FUNC!");
  1145. TraceMsg(L"CWlbsConfig::Install");
  1146. HRESULT hr = S_OK;
  1147. ASSERT_VALID(this);
  1148. /* Start up the install process. */
  1149. m_ServiceOperation = WLBS_SERVICE_INSTALL;
  1150. if (m_pWlbsComponent == NULL && FAILED(m_pNetCfg->FindComponent(NETCFG_WLBS_ID, &m_pWlbsComponent)) || m_pWlbsComponent == NULL) {
  1151. TraceError("INetCfg::FindComponent failed at Install",hr);
  1152. TRACE_CRIT("%!FUNC! find for nlb component object failed with %d", hr);
  1153. }
  1154. TRACE_VERB("->%!FUNC!");
  1155. return hr;
  1156. }
  1157. // ----------------------------------------------------------------------
  1158. //
  1159. // Function: CWlbsConfig::Upgrade
  1160. //
  1161. // Purpose: Do operations necessary for upgrade.
  1162. //
  1163. // Arguments:
  1164. // dwSetupFlags [in] Setup flags
  1165. //
  1166. // Returns: S_OK on success, otherwise an error code
  1167. //
  1168. // ----------------------------------------------------------------------
  1169. STDMETHODIMP CWlbsConfig::Upgrade(DWORD /* dwSetupFlags */, DWORD /* dwUpgradeFromBuildNo */) {
  1170. TRACE_VERB("->%!FUNC!");
  1171. TraceMsg(L"CWlbsConfig::Upgrade");
  1172. ASSERT_VALID(this);
  1173. /* If we do not have any cluster, there might be
  1174. old registry settings under different place. */
  1175. if (m_vtrCluster.size() == 0)
  1176. {
  1177. HRESULT hr = LoadAllAdapterSettings(true); // fUpgradeFromWin2k = true
  1178. if (FAILED(hr))
  1179. {
  1180. TRACE_CRIT("%!FUNC! loading all adapter settings for a window 2000 upgrade failed with %d", hr);
  1181. }
  1182. }
  1183. m_ServiceOperation = WLBS_SERVICE_UPGRADE;
  1184. TRACE_VERB("<-%!FUNC!");
  1185. return S_OK;
  1186. }
  1187. // ----------------------------------------------------------------------
  1188. //
  1189. // Function: CWlbsConfig::Removing
  1190. //
  1191. // Purpose: Do necessary cleanup when being removed
  1192. //
  1193. // Arguments: None
  1194. //
  1195. // Returns: S_OK on success, otherwise an error code
  1196. //
  1197. // Notes: Dont do anything irreversible (like modifying registry) yet
  1198. // since the removal is actually complete only when Apply is called!
  1199. //
  1200. // ----------------------------------------------------------------------
  1201. STDMETHODIMP CWlbsConfig::Removing(VOID) {
  1202. TRACE_VERB("->%!FUNC!");
  1203. TraceMsg(L"##### CWlbsConfig::Removing\n");
  1204. ASSERT_VALID(this);
  1205. m_ServiceOperation = WLBS_SERVICE_REMOVE;
  1206. TRACE_VERB("<-%!FUNC!");
  1207. return S_OK;
  1208. }
  1209. //+----------------------------------------------------------------------------
  1210. //
  1211. // Function: CWlbsConfig::GetAdapterConfig
  1212. //
  1213. // Description: Read the adapter config, which could be cached by SetAdapterConfig
  1214. //
  1215. // Arguments: const GUID& AdapterGuid -
  1216. // NETCFG_WLBS_CONFIG* pClusterConfig -
  1217. //
  1218. // Returns: STDMETHODIMP -
  1219. //
  1220. // History: fengsun Created Header 3/2/00
  1221. //
  1222. //+----------------------------------------------------------------------------
  1223. STDMETHODIMP CWlbsConfig::GetAdapterConfig(const GUID& AdapterGuid, NETCFG_WLBS_CONFIG* pClusterConfig) {
  1224. TRACE_VERB("->%!FUNC!");
  1225. TraceMsg(L"CWlbsConfig::GetAdapterConfig");
  1226. ASSERT_VALID(this);
  1227. ASSERT(pClusterConfig);
  1228. CNetcfgCluster* pCluster = GetCluster(AdapterGuid);
  1229. if (pCluster == NULL)
  1230. {
  1231. TRACE_INFO("%!FUNC! did not find cluster");
  1232. return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
  1233. }
  1234. pCluster->GetConfig(pClusterConfig); // Returns void
  1235. TRACE_VERB("<-%!FUNC!");
  1236. return S_OK;
  1237. }
  1238. //+----------------------------------------------------------------------------
  1239. //
  1240. // Function: CWlbsConfig::SetAdapterConfig
  1241. //
  1242. // Description: Set the adapter config, the result is cached and not saved to registry
  1243. //
  1244. // Arguments: const GUID& AdapterGuid -
  1245. // NETCFG_WLBS_CONFIG* pClusterConfig -
  1246. //
  1247. // Returns: STDMETHODIMP -
  1248. //
  1249. // History: fengsun Created Header 3/2/00
  1250. //
  1251. //+----------------------------------------------------------------------------
  1252. STDMETHODIMP CWlbsConfig::SetAdapterConfig(const GUID& AdapterGuid, NETCFG_WLBS_CONFIG* pClusterConfig) {
  1253. TRACE_VERB("->%!FUNC!");
  1254. TraceMsg(L"CWlbsConfig::SetAdapterConfig");
  1255. ASSERT_VALID(this);
  1256. ASSERT(pClusterConfig);
  1257. CNetcfgCluster* pCluster = GetCluster(AdapterGuid);
  1258. if (pCluster == NULL) {
  1259. TRACE_INFO("%!FUNC! did not find cluster. Will create instance");
  1260. pCluster = new CNetcfgCluster(this);
  1261. if (pCluster == NULL)
  1262. {
  1263. TRACE_CRIT("%!FUNC! memory allocation failure creating instance of CNetcfgCluster");
  1264. TRACE_VERB("<-%!FUNC!");
  1265. return E_OUTOFMEMORY;
  1266. }
  1267. pCluster->InitializeWithDefault(AdapterGuid); // Returns void
  1268. //
  1269. // See bug 233962, NLB configuration lost when leaving nlb properties
  1270. // The reason is that NLB notifier object is not notified when NLB is checked.
  1271. // Currently, there is no consistant repro. Uncommented the code below will fix the peoblem.
  1272. // But will leaves potential bug in netcfg hard to catch.
  1273. // Uncomment the code only after the netcfg bug is fixed.
  1274. //
  1275. // m_vtrCluster.push_back(pCluster);
  1276. }
  1277. pCluster->SetConfig(pClusterConfig); // Returns void
  1278. TRACE_VERB("<-%!FUNC!");
  1279. return S_OK;
  1280. }
  1281. // ----------------------------------------------------------------------
  1282. //
  1283. // Function: CWlbsConfig::ApplyRegistryChanges
  1284. //
  1285. // Purpose: Apply changes.
  1286. //
  1287. // Arguments: None
  1288. //
  1289. // Returns: S_OK on success, otherwise an error code
  1290. //
  1291. // Notes: We can make changes to registry etc. here.
  1292. //
  1293. // ----------------------------------------------------------------------
  1294. STDMETHODIMP CWlbsConfig::ApplyRegistryChanges(VOID) {
  1295. TRACE_VERB("->%!FUNC!");
  1296. TraceMsg(L"CWlbsConfig::ApplyRegistryChanges");
  1297. ASSERT_VALID(this);
  1298. for (vector<CNetcfgCluster*>::iterator iter = m_vtrCluster.begin(); iter != m_vtrCluster.end(); iter++) {
  1299. CNetcfgCluster* pCluster = *iter;
  1300. ASSERT(pCluster != NULL);
  1301. if (pCluster != NULL)
  1302. {
  1303. DWORD dwStatus = pCluster->ApplyRegistryChanges(m_ServiceOperation == WLBS_SERVICE_REMOVE);
  1304. if (ERROR_SUCCESS != dwStatus && WLBS_OK != dwStatus)
  1305. {
  1306. TRACE_CRIT("%!FUNC! applying registry changes to a CNetcfgCluster failed with %d. Continue with next instance", dwStatus);
  1307. }
  1308. }
  1309. else
  1310. {
  1311. TRACE_CRIT("%!FUNC! retrieved null instance of CNetcfgCluster");
  1312. }
  1313. }
  1314. TRACE_VERB("<-%!FUNC!");
  1315. return S_OK;
  1316. }
  1317. // ----------------------------------------------------------------------
  1318. //
  1319. // Function: CWlbsConfig::ApplyPnpChanges
  1320. //
  1321. // Purpose: Apply changes.
  1322. //
  1323. // Arguments: None
  1324. //
  1325. // Returns: S_OK on success, otherwise an error code
  1326. //
  1327. // Notes: Propagate changes to the driver.
  1328. //
  1329. // ----------------------------------------------------------------------
  1330. STDMETHODIMP CWlbsConfig::ApplyPnpChanges() {
  1331. TRACE_VERB("->%!FUNC!");
  1332. TraceMsg(L"CWlbsConfig::ApplyPnpChanges");
  1333. vector<CNetcfgCluster*>::iterator iter;
  1334. bool bCreateDevice = FALSE;
  1335. DWORD dwStatus = ERROR_SUCCESS;
  1336. ASSERT_VALID(this);
  1337. /* Check to see if we need to open the IOCTL interface to the driver. This is necessary
  1338. if any adapter in our cluster list requries a reload (which is done via an IOCTL). */
  1339. for (iter = m_vtrCluster.begin(); iter != m_vtrCluster.end(); iter++) {
  1340. CNetcfgCluster* pCluster = *iter;
  1341. if (bCreateDevice |= pCluster->IsReloadRequired()) break;
  1342. }
  1343. /* Open the file and return an error if this is unsuccessful. */
  1344. if (bCreateDevice) {
  1345. TRACE_INFO("%!FUNC! at least one adapter requires a reload. Open an IOCTL.");
  1346. ASSERT(m_hDeviceWlbs == INVALID_HANDLE_VALUE);
  1347. m_hDeviceWlbs = CreateFile(_TEXT("\\\\.\\WLBS"), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
  1348. if (m_hDeviceWlbs == INVALID_HANDLE_VALUE) {
  1349. dwStatus = GetLastError();
  1350. TraceMsg(L"Error opening \\\\.\\WLBS device %x", dwStatus);
  1351. TraceError("Invalid \\\\.\\WLBS handle", dwStatus);
  1352. TRACE_CRIT("%!FUNC! invalid handle opening \\\\.\\WLBS device. Error is %d", dwStatus);
  1353. return HRESULT_FROM_WIN32(dwStatus);
  1354. }
  1355. ASSERT(m_hDeviceWlbs != INVALID_HANDLE_VALUE);
  1356. }
  1357. for (iter = m_vtrCluster.begin(); iter != m_vtrCluster.end(); iter++) {
  1358. CNetcfgCluster* pCluster = *iter;
  1359. ASSERT(pCluster != NULL);
  1360. if (pCluster != NULL)
  1361. {
  1362. dwStatus = pCluster->ApplyPnpChanges(m_hDeviceWlbs);
  1363. if (ERROR_SUCCESS != dwStatus)
  1364. {
  1365. TRACE_CRIT("%!FUNC! apply pnp changes on CNetcfgCluster failed with %d", dwStatus);
  1366. }
  1367. }
  1368. else
  1369. {
  1370. TRACE_CRIT("%!FUNC! retrieved null instance of CNetcfgCluster");
  1371. }
  1372. }
  1373. if (m_hDeviceWlbs != INVALID_HANDLE_VALUE)
  1374. {
  1375. if (!CloseHandle(m_hDeviceWlbs))
  1376. {
  1377. dwStatus = GetLastError();
  1378. TRACE_CRIT("%!FUNC! close nlb device handle failed with %d", dwStatus);
  1379. }
  1380. }
  1381. TRACE_VERB("<-%!FUNC!");
  1382. return S_OK;
  1383. }
  1384. // ----------------------------------------------------------------------
  1385. //
  1386. // Function: CWlbsConfig::QueryBindingPath
  1387. //
  1388. // Purpose: Allow or veto a binding path involving us
  1389. //
  1390. // Arguments:
  1391. // dwChangeFlag [in] type of binding change
  1392. // pncbi [in] pointer to INetCfgBindingPath object
  1393. //
  1394. // Returns: S_OK on success, otherwise an error code
  1395. //
  1396. // Notes:
  1397. //
  1398. // ----------------------------------------------------------------------
  1399. STDMETHODIMP CWlbsConfig::QueryBindingPath(DWORD dwChangeFlag, INetCfgComponent* pAdapter) {
  1400. TRACE_VERB("->%!FUNC!");
  1401. TraceMsg(L"CWlbsConfig::QueryBindingPath");
  1402. ASSERT_VALID(this);
  1403. TRACE_VERB("<-%!FUNC!");
  1404. return NETCFG_S_DISABLE_QUERY;
  1405. }
  1406. // ----------------------------------------------------------------------
  1407. //
  1408. // Function: CWlbsConfig::NotifyBindingPath
  1409. //
  1410. // Purpose: System tells us by calling this function which
  1411. // binding path involving us has just been formed.
  1412. //
  1413. // Arguments:
  1414. // dwChangeFlag [in] type of binding change
  1415. // pncbp [in] pointer to INetCfgBindingPath object
  1416. //
  1417. // Returns: S_OK on success, otherwise an error code
  1418. //
  1419. // Notes:
  1420. //
  1421. // ----------------------------------------------------------------------
  1422. STDMETHODIMP CWlbsConfig::NotifyBindingPath(DWORD dwChangeFlag, INetCfgBindingPath* pncbp) {
  1423. TRACE_VERB("->%!FUNC!");
  1424. TraceMsg(L"CWlbsConfig::NotifyBindingPath");
  1425. HRESULT hr = S_OK;
  1426. INetCfgComponent * pAdapter;
  1427. PWSTR pszInterfaceName;
  1428. GUID AdapterGuid;
  1429. DWORD dwStatus = 0;
  1430. ASSERT_VALID(this);
  1431. if (m_pWlbsComponent == NULL && FAILED(m_pNetCfg->FindComponent(NETCFG_WLBS_ID, &m_pWlbsComponent)) || m_pWlbsComponent == NULL) {
  1432. dwStatus = GetLastError();
  1433. TraceError("NotifyBindingPath failed at INetCfg::FindComponent\n", dwStatus);
  1434. TRACE_CRIT("%!FUNC! find for nlb component object failed with %d", dwStatus);
  1435. TRACE_VERB("<-%!FUNC!");
  1436. return S_FALSE;
  1437. }
  1438. hr = HrGetLastComponentAndInterface (pncbp, &pAdapter, &pszInterfaceName);
  1439. if (FAILED(hr))
  1440. {
  1441. TRACE_CRIT("%!FUNC! enumerating binding path failed with %d", hr);
  1442. TRACE_VERB("<-%!FUNC!");
  1443. return hr;
  1444. }
  1445. CoTaskMemFree(pszInterfaceName);
  1446. hr = pAdapter->GetInstanceGuid(&AdapterGuid);
  1447. pAdapter->Release();
  1448. pAdapter = NULL;
  1449. if (FAILED(hr))
  1450. {
  1451. TRACE_CRIT("%!FUNC! retrieval of adapter guid from adapter failed with %d", hr);
  1452. TRACE_VERB("<-%!FUNC!");
  1453. return hr;
  1454. }
  1455. CNetcfgCluster* pCluster = GetCluster(AdapterGuid);
  1456. if (pCluster == NULL) {
  1457. if (dwChangeFlag & NCN_ENABLE) {
  1458. /* new configuration. */
  1459. pCluster = new CNetcfgCluster(this);
  1460. if (pCluster == NULL)
  1461. {
  1462. TRACE_CRIT("%!FUNC! memory allocation failure creating instance of CNetcfgCluster");
  1463. TRACE_VERB("<-%!FUNC!");
  1464. return E_OUTOFMEMORY;
  1465. }
  1466. pCluster->InitializeWithDefault(AdapterGuid); // Returns void
  1467. m_vtrCluster.push_back(pCluster);
  1468. } else {
  1469. TraceMsg(L"CWlbsConfig::NotifyBindingPath adapter not bound");
  1470. TRACE_INFO("%!FUNC! adapter is not bound");
  1471. TRACE_VERB("<-%!FUNC!");
  1472. return S_OK;
  1473. }
  1474. }
  1475. pCluster->NotifyBindingChanges(dwChangeFlag, pncbp); // Returns void
  1476. /* If we are enabling a binding path, then check for cluster IP address conflicts. */
  1477. if (dwChangeFlag & NCN_ENABLE) {
  1478. NETCFG_WLBS_CONFIG adapterConfig;
  1479. /* Retrieve the cluster configuration. */
  1480. pCluster->GetConfig(&adapterConfig); // Returns void
  1481. /* If we detect another bound adapter with this cluster IP address, then revert this cluster's
  1482. cluster IP Address to the default value. If the user opens the property dialog, they can
  1483. change the IP address, but we CANNOT warn them here - this code can be run programmatically.
  1484. However, because the user CAN bind NLB without opening the properties, we MUST check this here. */
  1485. if ((hr = CheckForDuplicateCLusterIPAddresses(AdapterGuid, &adapterConfig)) != S_OK) {
  1486. TRACE_CRIT("%!FUNC! another adapter is bound and has the same cluster IP address %ls. Status of check is %d", adapterConfig.cl_ip_addr, hr);
  1487. /* Revert this cluster IP Address to the default (0.0.0.0). */
  1488. lstrcpy(adapterConfig.cl_ip_addr, CVY_DEF_CL_IP_ADDR);
  1489. /* Revert this cluster IP Address to the default (0.0.0.0). */
  1490. lstrcpy(adapterConfig.cl_net_mask, CVY_DEF_CL_NET_MASK);
  1491. /* Set the cluster configuration. */
  1492. pCluster->SetConfig(&adapterConfig); // Returns void
  1493. }
  1494. }
  1495. TRACE_VERB("<-%!FUNC!");
  1496. return S_OK;
  1497. }
  1498. //+----------------------------------------------------------------------------
  1499. //
  1500. // Function: CWlbsConfig::GetCluster
  1501. //
  1502. // Description:
  1503. //
  1504. // Arguments: const GUID& AdapterGuid -
  1505. //
  1506. // Returns: CNetcfgCluster* -
  1507. //
  1508. // History: fengsun Created Header 2/14/00
  1509. //
  1510. //+----------------------------------------------------------------------------
  1511. CNetcfgCluster* CWlbsConfig::GetCluster(const GUID& AdapterGuid) {
  1512. TRACE_VERB("->%!FUNC!");
  1513. TraceMsg(L"CWlbsConfig::GetCluster");
  1514. ASSERT_VALID(this);
  1515. for (vector<CNetcfgCluster*>::iterator iter = m_vtrCluster.begin(); iter != m_vtrCluster.end(); iter++) {
  1516. CNetcfgCluster* pCluster = *iter;
  1517. ASSERT(pCluster != NULL);
  1518. if (pCluster != NULL) {
  1519. if (IsEqualGUID(pCluster->GetAdapterGuid(), AdapterGuid))
  1520. {
  1521. TRACE_INFO("%!FUNC! cluster instance found");
  1522. TRACE_VERB("<-%!FUNC!");
  1523. return pCluster;
  1524. }
  1525. }
  1526. else
  1527. {
  1528. TRACE_CRIT("%!FUNC! retrieved null instance of CNetcfgCluster. Skipping it.");
  1529. }
  1530. }
  1531. TRACE_INFO("%!FUNC! cluster instance not found");
  1532. TRACE_VERB("<-%!FUNC!");
  1533. return NULL;
  1534. }
  1535. //+----------------------------------------------------------------------------
  1536. //
  1537. // Function: CWlbsConfig::IsBoundTo
  1538. //
  1539. // Description:
  1540. //
  1541. // Arguments: INetCfgComponent* pAdapter -
  1542. //
  1543. // Returns: HRESULT -
  1544. //
  1545. // History: fengsun Created Header 2/14/00
  1546. //
  1547. //+----------------------------------------------------------------------------
  1548. HRESULT CWlbsConfig::IsBoundTo(INetCfgComponent* pAdapter) {
  1549. TRACE_VERB("->%!FUNC!");
  1550. TraceMsg(L"CWlbsConfig::IsBoundTo");
  1551. HRESULT hr;
  1552. ASSERT_VALID(this);
  1553. ASSERT(pAdapter != NULL);
  1554. if (m_pWlbsComponent == NULL) {
  1555. TraceMsg(L"CWlbsConfig::IsBoundTo wlbs not installed");
  1556. TRACE_INFO("%!FUNC! nlb is not installed");
  1557. TRACE_VERB("<-%!FUNC!");
  1558. return S_FALSE;
  1559. }
  1560. INetCfgComponentBindings *pIBinding = NULL;
  1561. if (FAILED(m_pWlbsComponent->QueryInterface(IID_INetCfgComponentBindings, (void**)&pIBinding))) {
  1562. DWORD dwStatus = GetLastError();
  1563. TraceError("QI for INetCfgComponentBindings failed\n", dwStatus);
  1564. TRACE_INFO("%!FUNC! QueryInterface on the nlb component object failed with %d", dwStatus);
  1565. }
  1566. if (FAILED(hr = pIBinding->IsBoundTo(pAdapter))) {
  1567. TraceError("Failed to IsBoundTo", hr);
  1568. TRACE_INFO("%!FUNC! the check whether nlb is bound to an adapter failed with %d", hr);
  1569. }
  1570. if (pIBinding) pIBinding->Release();
  1571. TRACE_VERB("<-%!FUNC!");
  1572. return hr;
  1573. }
  1574. //+----------------------------------------------------------------------------
  1575. //
  1576. // Function: CWlbsConfig::SetDefaults
  1577. //
  1578. // Description:
  1579. //
  1580. // Arguments: NETCFG_WLBS_CONFIG* pClusterConfig -
  1581. //
  1582. // Returns: Nothing
  1583. //
  1584. // History: fengsun Created Header 2/14/00
  1585. //
  1586. //+----------------------------------------------------------------------------
  1587. void CWlbsConfig::SetDefaults(NETCFG_WLBS_CONFIG* pClusterConfig) {
  1588. TRACE_VERB("->%!FUNC!");
  1589. TraceMsg(L"CWlbsConfig::SetDefaults");
  1590. WLBS_REG_PARAMS config;
  1591. ASSERT_VALID(this);
  1592. ASSERT(pClusterConfig);
  1593. ASSERT(m_pWlbsApiFuncs);
  1594. ASSERT(m_pWlbsApiFuncs->pfnParamSetDefaults);
  1595. DWORD dwStatus = m_pWlbsApiFuncs->pfnParamSetDefaults(&config);
  1596. if (WLBS_OK != dwStatus)
  1597. {
  1598. TRACE_CRIT("%!FUNC! failed to set defaults for the cluster configuration");
  1599. }
  1600. WlbsToNetcfgConfig(m_pWlbsApiFuncs, &config, pClusterConfig); // Returns void
  1601. TRACE_VERB("<-%!FUNC!");
  1602. }
  1603. /*
  1604. * Function: CWlbsConfig::ValidateProperties
  1605. * Description: Check for conflicting cluster IP addresses and alert the user.
  1606. * Author: shouse 7.13.00
  1607. */
  1608. STDMETHODIMP CWlbsConfig::ValidateProperties (HWND hwndSheet, GUID adapterGUID, NETCFG_WLBS_CONFIG * adapterConfig) {
  1609. TRACE_VERB("->%!FUNC!");
  1610. TraceMsg(L"CWlbsConfig::ValidateProperties");
  1611. HRESULT hr = S_OK;
  1612. ASSERT_VALID(this);
  1613. /* If we detect another bound adapter with this cluster IP address, then fail the check and
  1614. pop-up an error message warning the user that there are conflicting IP addresses. */
  1615. if ((hr = CheckForDuplicateCLusterIPAddresses(adapterGUID, adapterConfig)) != S_OK)
  1616. {
  1617. NcMsgBox(hwndSheet, IDS_PARM_ERROR, IDS_PARM_MULTINIC_IP_CONFLICT, MB_APPLMODAL | MB_ICONSTOP | MB_OK);
  1618. TRACE_CRIT("%!FUNC! another network adapter is using IP address %ls", adapterConfig->cl_ip_addr);
  1619. }
  1620. TRACE_VERB("<-%!FUNC!");
  1621. return hr;
  1622. }
  1623. /*
  1624. * Function: CWlbsConfig::CheckForDuplicateCLusterIPAddresses
  1625. * Description: Loop through all adapters and check for conflicting cluster IP addresses.
  1626. * Author: shouse 7.13.00
  1627. */
  1628. STDMETHODIMP CWlbsConfig::CheckForDuplicateCLusterIPAddresses (GUID adapterGUID, NETCFG_WLBS_CONFIG * adapterConfig) {
  1629. TRACE_VERB("->%!FUNC!");
  1630. TraceMsg(L"CWlbsConfig::CheckForDuplicateCLusterIPAddresses");
  1631. CNetcfgCluster * pClusterMe = NULL;
  1632. ASSERT_VALID(this);
  1633. /* Get the cluster pointer for this adapter GUID. */
  1634. pClusterMe = GetCluster(adapterGUID);
  1635. ASSERT(pClusterMe);
  1636. if (!pClusterMe)
  1637. {
  1638. TRACE_INFO("%!FUNC! no cluster instance was found for the supplied adapter");
  1639. TRACE_VERB("<-%!FUNC!");
  1640. return S_OK;
  1641. }
  1642. /* If the cluster IP address is the default, then don't check other adapters because
  1643. if they have not been configured yet, this may cause confusion for the user. We
  1644. will ignore the error here and other validation in the cluster properties should
  1645. catch this error instead. */
  1646. if (!lstrcmpi(adapterConfig->cl_ip_addr, CVY_DEF_CL_IP_ADDR))
  1647. {
  1648. TRACE_INFO("%!FUNC! the adapter config is using the default cluster IP address. No checking needed.");
  1649. TRACE_VERB("<-%!FUNC!");
  1650. return S_OK;
  1651. }
  1652. /* Loop through the rest of the list and check this cluster IP against the cluster
  1653. IP of each adapter left in the list. */
  1654. for (vector<CNetcfgCluster *>::iterator iter = m_vtrCluster.begin(); iter != m_vtrCluster.end(); iter++) {
  1655. CNetcfgCluster * pCluster = *iter;
  1656. ASSERT(pCluster);
  1657. if (!pCluster)
  1658. {
  1659. /* CLD: 05.17.01 is this a no op or do we store nulls in the vector? */
  1660. TRACE_INFO("%!FUNC! Found NULL pointer to a CNetcfgCluster. No further checking needed.");
  1661. TRACE_VERB("<-%!FUNC!");
  1662. return S_OK;
  1663. }
  1664. /* Obviously, don't check against myself. */
  1665. if (pClusterMe == pCluster) continue;
  1666. /* If we find a match, report and error and do not allow the dialog to close. */
  1667. if (pCluster->CheckForDuplicateClusterIPAddress(adapterConfig->cl_ip_addr))
  1668. {
  1669. TRACE_INFO("%!FUNC! duplicate cluster IP address found.");
  1670. TRACE_VERB("<-%!FUNC!");
  1671. return S_FALSE;
  1672. }
  1673. }
  1674. TRACE_VERB("<-%!FUNC!");
  1675. return S_OK;
  1676. }
  1677. //+----------------------------------------------------------------------------
  1678. //
  1679. // Function: WlbsToNetcfgConfig
  1680. //
  1681. // Description:
  1682. //
  1683. // Arguments: const WLBS_REG_PARAMS* pWlbsConfig -
  1684. // NETCFG_WLBS_CONFIG* pNetcfgConfig -
  1685. //
  1686. // Returns: Nothing
  1687. //
  1688. // History: fengsun Created Header 2/14/00
  1689. //
  1690. //+----------------------------------------------------------------------------
  1691. void WlbsToNetcfgConfig(const WlbsApiFuncs* pWlbsApiFuncs, const WLBS_REG_PARAMS* pWlbsConfig, NETCFG_WLBS_CONFIG* pNetcfgConfig) {
  1692. TRACE_VERB("->%!FUNC!");
  1693. TraceMsg(L"WlbsToNetcfgConfig");
  1694. ASSERT(pNetcfgConfig != NULL);
  1695. ASSERT(pWlbsConfig != NULL);
  1696. ASSERT(pWlbsApiFuncs);
  1697. ASSERT(pWlbsApiFuncs->pfnWlbsEnumPortRules);
  1698. pNetcfgConfig->dwHostPriority = pWlbsConfig->host_priority;
  1699. pNetcfgConfig->fRctEnabled = (pWlbsConfig->rct_enabled != FALSE);
  1700. pNetcfgConfig->fJoinClusterOnBoot = (pWlbsConfig->cluster_mode != FALSE);
  1701. pNetcfgConfig->fMcastSupport = (pWlbsConfig->mcast_support != FALSE);
  1702. pNetcfgConfig->fIGMPSupport = (pWlbsConfig->fIGMPSupport != FALSE);
  1703. pNetcfgConfig->fIpToMCastIp = (pWlbsConfig->fIpToMCastIp != FALSE);
  1704. pNetcfgConfig->fConvertMac = (pWlbsConfig->i_convert_mac != FALSE);
  1705. pNetcfgConfig->dwMaxHosts = pWlbsConfig->i_max_hosts;
  1706. pNetcfgConfig->dwMaxRules = pWlbsConfig->i_max_rules;
  1707. lstrcpy(pNetcfgConfig->szMCastIpAddress, pWlbsConfig->szMCastIpAddress);
  1708. lstrcpy(pNetcfgConfig->cl_mac_addr, pWlbsConfig->cl_mac_addr);
  1709. lstrcpy(pNetcfgConfig->cl_ip_addr, pWlbsConfig->cl_ip_addr);
  1710. lstrcpy(pNetcfgConfig->cl_net_mask, pWlbsConfig->cl_net_mask);
  1711. lstrcpy(pNetcfgConfig->ded_ip_addr, pWlbsConfig->ded_ip_addr);
  1712. lstrcpy(pNetcfgConfig->ded_net_mask, pWlbsConfig->ded_net_mask);
  1713. lstrcpy(pNetcfgConfig->domain_name, pWlbsConfig->domain_name);
  1714. pNetcfgConfig->fChangePassword =false;
  1715. pNetcfgConfig->szPassword[0] = L'\0';
  1716. ZeroMemory(pNetcfgConfig->port_rules, sizeof(pNetcfgConfig->port_rules));
  1717. WLBS_PORT_RULE PortRules[WLBS_MAX_RULES];
  1718. DWORD dwNumRules = WLBS_MAX_RULES;
  1719. if (pWlbsApiFuncs->pfnWlbsEnumPortRules((WLBS_REG_PARAMS*)pWlbsConfig, PortRules, &dwNumRules)!= WLBS_OK) {
  1720. DWORD dwStatus = GetLastError();
  1721. TraceError("CNetcfgCluster::GetConfig failed at WlbsEnumPortRules", dwStatus);
  1722. TRACE_CRIT("%!FUNC! api call to enumerate port rules failed with %d", dwStatus);
  1723. TRACE_VERB("<-%!FUNC!");
  1724. return;
  1725. }
  1726. ASSERT(dwNumRules <= WLBS_MAX_RULES);
  1727. pNetcfgConfig->dwNumRules = dwNumRules;
  1728. for (DWORD i=0; i<dwNumRules; i++) {
  1729. lstrcpy(pNetcfgConfig->port_rules[i].virtual_ip_addr, PortRules[i].virtual_ip_addr);
  1730. pNetcfgConfig->port_rules[i].start_port = PortRules[i].start_port;
  1731. pNetcfgConfig->port_rules[i].end_port = PortRules[i].end_port;
  1732. pNetcfgConfig->port_rules[i].mode = PortRules[i].mode;
  1733. pNetcfgConfig->port_rules[i].protocol = PortRules[i].protocol;
  1734. if (pNetcfgConfig->port_rules[i].mode == WLBS_AFFINITY_SINGLE) {
  1735. pNetcfgConfig->port_rules[i].mode_data.single.priority =
  1736. PortRules[i].mode_data.single.priority;
  1737. } else {
  1738. pNetcfgConfig->port_rules[i].mode_data.multi.equal_load =
  1739. PortRules[i].mode_data.multi.equal_load;
  1740. pNetcfgConfig->port_rules[i].mode_data.multi.affinity =
  1741. PortRules[i].mode_data.multi.affinity;
  1742. pNetcfgConfig->port_rules[i].mode_data.multi.load =
  1743. PortRules[i].mode_data.multi.load;
  1744. }
  1745. }
  1746. }
  1747. #if DBG
  1748. void TraceMsg(PCWSTR pszFormat, ...) {
  1749. static WCHAR szTempBufW[4096];
  1750. static CHAR szTempBufA[4096];
  1751. va_list arglist;
  1752. va_start(arglist, pszFormat);
  1753. vswprintf(szTempBufW, pszFormat, arglist);
  1754. /* Convert the WCHAR to CHAR. This is for backward compatability with TraceMsg
  1755. so that it was not necessary to change all pre-existing calls thereof. */
  1756. WideCharToMultiByte(CP_ACP, 0, szTempBufW, -1, szTempBufA, 4096, NULL, NULL);
  1757. /* Traced messages are now sent through the netcfg TraceTag routine so that
  1758. they can be turned on/off dynamically. */
  1759. TraceTag(ttidWlbs, szTempBufA);
  1760. va_end(arglist);
  1761. }
  1762. #endif
  1763. #ifdef DEBUG
  1764. void CWlbsConfig::AssertValid() {
  1765. ASSERT(m_ServiceOperation >= WLBS_SERVICE_NONE && m_ServiceOperation <= WLBS_SERVICE_UPGRADE);
  1766. ASSERT(m_pNetCfg != NULL);
  1767. ASSERT(m_hdllWlbsCtrl != NULL);
  1768. ASSERT(m_pWlbsApiFuncs != NULL);
  1769. ASSERT (m_pWlbsApiFuncs->pfnParamReadReg != NULL);
  1770. ASSERT (m_pWlbsApiFuncs->pfnParamWriteReg != NULL);
  1771. ASSERT (m_pWlbsApiFuncs->pfnParamDeleteReg != NULL);
  1772. ASSERT (m_pWlbsApiFuncs->pfnParamSetDefaults != NULL);
  1773. ASSERT (m_pWlbsApiFuncs->pfnRegChangeNetworkAddress != NULL);
  1774. ASSERT (m_pWlbsApiFuncs->pfnNotifyAdapterAddressChange != NULL);
  1775. ASSERT (m_pWlbsApiFuncs->pfnWlbsAddPortRule != NULL);
  1776. ASSERT (m_pWlbsApiFuncs->pfnWlbsSetRemotePassword != NULL);
  1777. ASSERT (m_pWlbsApiFuncs->pfnWlbsEnumPortRules != NULL);
  1778. ASSERT (m_pWlbsApiFuncs->pfnNotifyDriverConfigChanges != NULL);
  1779. ASSERT(m_vtrCluster.size()<=128);
  1780. }
  1781. #endif
  1782. //+----------------------------------------------------------------------------
  1783. //
  1784. // Function: ParamReadAnswerFile
  1785. //
  1786. // Description:
  1787. //
  1788. // Arguments: CWSTR answer_file -
  1789. // PCWSTR answer_sections -
  1790. // WLBS_REG_PARAMS* paramp -
  1791. //
  1792. // Returns: HRESULT -
  1793. //
  1794. // History: fengsun Created Header 3/2/00
  1795. //
  1796. //+----------------------------------------------------------------------------
  1797. HRESULT ParamReadAnswerFile(CSetupInfFile& caf, PCWSTR answer_sections, WLBS_REG_PARAMS* paramp) {
  1798. TRACE_VERB("->%!FUNC!");
  1799. TraceMsg(L"ParamReadAnswerFile");
  1800. HRESULT hr = S_OK;
  1801. tstring str;
  1802. DWORD dword;
  1803. ULONG i, code;
  1804. PWLBS_PORT_RULE rp;
  1805. INFCONTEXT ctx;
  1806. PWCHAR port_str;
  1807. hr = caf.HrGetDword(answer_sections, CVY_NAME_VERSION, & dword);
  1808. if (SUCCEEDED(hr)) {
  1809. paramp -> i_parms_ver = dword;
  1810. TRACE_VERB("%!FUNC! read %ls %d", CVY_NAME_VERSION, paramp -> i_parms_ver);
  1811. TraceMsg(L"#### ParamReadAnswerFile read %ls %d", CVY_NAME_VERSION, paramp -> i_parms_ver);
  1812. }
  1813. else
  1814. {
  1815. TRACE_CRIT("%!FUNC! failed reading %ls. Retrieved %d", CVY_NAME_VERSION, paramp -> i_parms_ver);
  1816. }
  1817. hr = caf.HrGetDword(answer_sections, CVY_NAME_HOST_PRIORITY, & dword);
  1818. if (SUCCEEDED(hr)) {
  1819. paramp -> host_priority = dword;
  1820. TRACE_VERB("%!FUNC! read %ls %d", CVY_NAME_HOST_PRIORITY, paramp -> host_priority);
  1821. TraceMsg(L"#### ParamReadAnswerFile read %ls %d\n", CVY_NAME_HOST_PRIORITY, paramp -> host_priority);
  1822. }
  1823. else
  1824. {
  1825. TRACE_CRIT("%!FUNC! failed reading %ls. Retrieved %d", CVY_NAME_HOST_PRIORITY, paramp -> host_priority);
  1826. }
  1827. hr = caf.HrGetDword(answer_sections, CVY_NAME_CLUSTER_MODE, & dword);
  1828. if (SUCCEEDED(hr)) {
  1829. paramp -> cluster_mode = dword;
  1830. TRACE_VERB("%!FUNC! read %ls %d", CVY_NAME_CLUSTER_MODE, paramp -> cluster_mode);
  1831. TraceMsg(L"#### ParamReadAnswerFile read %ls %d\n", CVY_NAME_CLUSTER_MODE, paramp -> cluster_mode);
  1832. }
  1833. else
  1834. {
  1835. TRACE_CRIT("%!FUNC! failed reading %ls. Retrieved %d", CVY_NAME_CLUSTER_MODE, paramp -> cluster_mode);
  1836. }
  1837. hr = caf.HrGetString(answer_sections, CVY_NAME_NETWORK_ADDR, & str);
  1838. if (SUCCEEDED(hr)) {
  1839. wcsncpy(paramp -> cl_mac_addr, str.c_str(), wcslen(str.c_str()) > sizeof (paramp -> cl_mac_addr) - sizeof (WCHAR) ?
  1840. sizeof (paramp -> cl_mac_addr) - sizeof (WCHAR) : wcslen(str.c_str()) + 1);
  1841. TRACE_VERB("%!FUNC! read %ls %ls", CVY_NAME_NETWORK_ADDR, paramp -> cl_mac_addr);
  1842. TraceMsg(L"#### ParamReadAnswerFile read %ls %ls\n", CVY_NAME_NETWORK_ADDR, paramp -> cl_mac_addr);
  1843. }
  1844. else
  1845. {
  1846. if (NULL != str.c_str())
  1847. {
  1848. TRACE_CRIT("%!FUNC! failed reading %ls. Retrieved %ls", CVY_NAME_NETWORK_ADDR, str.c_str());
  1849. } else {
  1850. TRACE_CRIT("%!FUNC! failed reading %ls. String was not retrieved", CVY_NAME_NETWORK_ADDR);
  1851. }
  1852. }
  1853. hr = caf.HrGetString(answer_sections, CVY_NAME_CL_IP_ADDR, & str);
  1854. if (SUCCEEDED(hr)) {
  1855. wcsncpy(paramp -> cl_ip_addr, str.c_str(), wcslen(str.c_str()) > sizeof (paramp -> cl_ip_addr) - sizeof (WCHAR) ?
  1856. sizeof (paramp -> cl_ip_addr) - sizeof (WCHAR) : wcslen(str.c_str()) + 1);
  1857. TRACE_VERB("%!FUNC! read %ls %ls", CVY_NAME_CL_IP_ADDR, paramp -> cl_ip_addr);
  1858. TraceMsg(L"#### ParamReadAnswerFile read %ls %ls\n", CVY_NAME_CL_IP_ADDR, paramp -> cl_ip_addr);
  1859. }
  1860. else
  1861. {
  1862. TRACE_CRIT("%!FUNC! failed reading %ls.", CVY_NAME_CL_IP_ADDR);
  1863. }
  1864. hr = caf.HrGetString(answer_sections, CVY_NAME_CL_NET_MASK, & str);
  1865. if (SUCCEEDED(hr)) {
  1866. wcsncpy(paramp -> cl_net_mask, str.c_str(), wcslen(str.c_str()) > sizeof (paramp -> cl_net_mask) - sizeof (WCHAR) ?
  1867. sizeof (paramp -> cl_net_mask) - sizeof (WCHAR) : wcslen(str.c_str()) + 1);
  1868. TRACE_VERB("%!FUNC! read %ls %ls", CVY_NAME_CL_NET_MASK, paramp -> cl_net_mask);
  1869. TraceMsg(L"#### ParamReadAnswerFile read %ls %ls\n", CVY_NAME_CL_NET_MASK, paramp -> cl_net_mask);
  1870. }
  1871. else
  1872. {
  1873. TRACE_CRIT("%!FUNC! failed reading %ls.", CVY_NAME_CL_NET_MASK);
  1874. }
  1875. hr = caf.HrGetString(answer_sections, CVY_NAME_DED_IP_ADDR, & str);
  1876. if (SUCCEEDED(hr)) {
  1877. wcsncpy(paramp -> ded_ip_addr, str.c_str(), wcslen(str.c_str()) > sizeof (paramp -> ded_ip_addr) - sizeof (WCHAR) ?
  1878. sizeof (paramp -> ded_ip_addr) - sizeof (WCHAR) : wcslen(str.c_str()) + 1);
  1879. TRACE_VERB("%!FUNC! read %ls %ls", CVY_NAME_DED_IP_ADDR, paramp -> ded_ip_addr);
  1880. TraceMsg(L"#### ParamReadAnswerFile read %ls %ls\n", CVY_NAME_DED_IP_ADDR, paramp -> ded_ip_addr);
  1881. }
  1882. else
  1883. {
  1884. TRACE_CRIT("%!FUNC! failed reading %ls", CVY_NAME_DED_IP_ADDR);
  1885. }
  1886. hr = caf.HrGetString(answer_sections, CVY_NAME_DED_NET_MASK, & str);
  1887. if (SUCCEEDED(hr)) {
  1888. wcsncpy(paramp -> ded_net_mask, str.c_str(), wcslen(str.c_str()) > sizeof (paramp -> ded_net_mask) - sizeof (WCHAR) ?
  1889. sizeof (paramp -> ded_net_mask) - sizeof (WCHAR) : wcslen(str.c_str()) + 1);
  1890. TRACE_VERB("%!FUNC! read %ls %ls", CVY_NAME_DED_NET_MASK, paramp -> ded_net_mask);
  1891. TraceMsg(L"#### ParamReadAnswerFile read %ls %ls\n", CVY_NAME_DED_NET_MASK, paramp -> ded_net_mask);
  1892. }
  1893. else
  1894. {
  1895. TRACE_CRIT("%!FUNC! failed reading %ls.", CVY_NAME_DED_NET_MASK);
  1896. }
  1897. hr = caf.HrGetString(answer_sections, CVY_NAME_DOMAIN_NAME, & str);
  1898. if (SUCCEEDED(hr)) {
  1899. wcsncpy(paramp -> domain_name, str.c_str(), wcslen(str.c_str()) > sizeof (paramp -> domain_name) - sizeof (WCHAR) ?
  1900. sizeof (paramp -> domain_name) - sizeof (WCHAR) : wcslen(str.c_str()) + 1);
  1901. TRACE_VERB("%!FUNC! read %ls %ls", CVY_NAME_DOMAIN_NAME, paramp -> domain_name);
  1902. TraceMsg(L"#### ParamReadAnswerFile read %ls %ls\n", CVY_NAME_DOMAIN_NAME, paramp -> domain_name);
  1903. }
  1904. else
  1905. {
  1906. TRACE_CRIT("%!FUNC! failed reading %ls.", CVY_NAME_DOMAIN_NAME);
  1907. }
  1908. hr = caf.HrGetDword(answer_sections, CVY_NAME_ALIVE_PERIOD, & dword);
  1909. if (SUCCEEDED(hr)) {
  1910. paramp -> alive_period = dword;
  1911. TRACE_VERB("%!FUNC! read %ls %d", CVY_NAME_ALIVE_PERIOD, paramp -> alive_period);
  1912. TraceMsg(L"#### ParamReadAnswerFile read %ls %d\n", CVY_NAME_ALIVE_PERIOD, paramp -> alive_period);
  1913. }
  1914. else
  1915. {
  1916. TRACE_CRIT("%!FUNC! failed reading %ls. Retrieved %d", CVY_NAME_ALIVE_PERIOD, paramp -> alive_period);
  1917. }
  1918. hr = caf.HrGetDword(answer_sections, CVY_NAME_ALIVE_TOLER, & dword);
  1919. if (SUCCEEDED(hr)) {
  1920. paramp -> alive_tolerance = dword;
  1921. TRACE_VERB("%!FUNC! read %ls %d", CVY_NAME_ALIVE_TOLER, paramp -> alive_tolerance);
  1922. TraceMsg(L"#### ParamReadAnswerFile read %ls %d\n", CVY_NAME_ALIVE_TOLER, paramp -> alive_tolerance);
  1923. }
  1924. else
  1925. {
  1926. TRACE_CRIT("%!FUNC! failed reading %ls. Retrieved %d", CVY_NAME_ALIVE_TOLER, paramp -> alive_tolerance);
  1927. }
  1928. hr = caf.HrGetDword(answer_sections, CVY_NAME_NUM_ACTIONS, & dword);
  1929. if (SUCCEEDED(hr)) {
  1930. paramp -> num_actions = dword;
  1931. TRACE_VERB("%!FUNC! read %ls %d", CVY_NAME_NUM_ACTIONS, paramp -> num_actions);
  1932. TraceMsg(L"#### ParamReadAnswerFile read %ls %d\n", CVY_NAME_NUM_ACTIONS, paramp -> num_actions);
  1933. }
  1934. else
  1935. {
  1936. TRACE_CRIT("%!FUNC! failed reading %ls. Retrieved %d", CVY_NAME_NUM_ACTIONS, paramp -> num_actions);
  1937. }
  1938. hr = caf.HrGetDword(answer_sections, CVY_NAME_NUM_PACKETS, & dword);
  1939. if (SUCCEEDED(hr)) {
  1940. paramp -> num_packets = dword;
  1941. TRACE_VERB("%!FUNC! read %ls %d", CVY_NAME_NUM_PACKETS, paramp -> num_packets);
  1942. TraceMsg(L"#### ParamReadAnswerFile read %ls %d\n", CVY_NAME_NUM_PACKETS, paramp -> num_packets);
  1943. }
  1944. else
  1945. {
  1946. TRACE_CRIT("%!FUNC! failed reading %ls. Retrieved %d", CVY_NAME_NUM_PACKETS, paramp -> num_packets);
  1947. }
  1948. hr = caf.HrGetDword(answer_sections, CVY_NAME_NUM_SEND_MSGS, & dword);
  1949. if (SUCCEEDED(hr)) {
  1950. paramp -> num_send_msgs = dword;
  1951. TRACE_VERB("%!FUNC! read %ls %d", CVY_NAME_NUM_SEND_MSGS, paramp -> num_send_msgs);
  1952. TraceMsg(L"#### ParamReadAnswerFile read %ls %d\n", CVY_NAME_NUM_SEND_MSGS, paramp -> num_send_msgs);
  1953. }
  1954. else
  1955. {
  1956. TRACE_CRIT("%!FUNC! failed reading %ls. Retrieved %d", CVY_NAME_NUM_SEND_MSGS, paramp -> num_send_msgs);
  1957. }
  1958. hr = caf.HrGetDword(answer_sections, CVY_NAME_DSCR_PER_ALLOC, & dword);
  1959. if (SUCCEEDED(hr)) {
  1960. paramp -> dscr_per_alloc = dword;
  1961. TRACE_VERB("%!FUNC! read %ls %d", CVY_NAME_DSCR_PER_ALLOC, paramp -> dscr_per_alloc);
  1962. TraceMsg(L"#### ParamReadAnswerFile read %ls %d\n", CVY_NAME_DSCR_PER_ALLOC, paramp -> dscr_per_alloc);
  1963. }
  1964. else
  1965. {
  1966. TRACE_CRIT("%!FUNC! failed reading %ls. Retrieved %d", CVY_NAME_DSCR_PER_ALLOC, paramp -> dscr_per_alloc);
  1967. }
  1968. hr = caf.HrGetDword(answer_sections, CVY_NAME_MAX_DSCR_ALLOCS, & dword);
  1969. if (SUCCEEDED(hr)) {
  1970. paramp -> max_dscr_allocs = dword;
  1971. TRACE_VERB("%!FUNC! read %ls %d", CVY_NAME_MAX_DSCR_ALLOCS, paramp -> max_dscr_allocs);
  1972. TraceMsg(L"#### ParamReadAnswerFile read %ls %d\n", CVY_NAME_MAX_DSCR_ALLOCS, paramp -> max_dscr_allocs);
  1973. }
  1974. else
  1975. {
  1976. TRACE_CRIT("%!FUNC! failed reading %ls. Retrieved %d", CVY_NAME_MAX_DSCR_ALLOCS, paramp -> max_dscr_allocs);
  1977. }
  1978. hr = caf.HrGetDword(answer_sections, CVY_NAME_SCALE_CLIENT, & dword);
  1979. if (SUCCEEDED(hr)) {
  1980. paramp -> i_scale_client = dword;
  1981. TRACE_VERB("%!FUNC! read %ls %d", CVY_NAME_SCALE_CLIENT, paramp -> i_scale_client);
  1982. TraceMsg(L"#### ParamReadAnswerFile read %ls %d\n", CVY_NAME_SCALE_CLIENT, paramp -> i_scale_client);
  1983. }
  1984. else
  1985. {
  1986. TRACE_CRIT("%!FUNC! failed reading %ls. Retrieved %d", CVY_NAME_SCALE_CLIENT, paramp -> i_scale_client);
  1987. }
  1988. hr = caf.HrGetDword(answer_sections, CVY_NAME_CLEANUP_DELAY, & dword);
  1989. if (SUCCEEDED(hr)) {
  1990. paramp -> i_cleanup_delay = dword;
  1991. TRACE_VERB("%!FUNC! read %ls %d", CVY_NAME_CLEANUP_DELAY, paramp -> i_cleanup_delay);
  1992. TraceMsg(L"#### ParamReadAnswerFile read %ls %d\n", CVY_NAME_CLEANUP_DELAY, paramp -> i_cleanup_delay);
  1993. }
  1994. else
  1995. {
  1996. TRACE_CRIT("%!FUNC! failed reading %ls. Retrieved %d", CVY_NAME_CLEANUP_DELAY, paramp -> i_cleanup_delay);
  1997. }
  1998. hr = caf.HrGetDword(answer_sections, CVY_NAME_NBT_SUPPORT, & dword);
  1999. if (SUCCEEDED(hr)) {
  2000. paramp -> i_nbt_support = dword;
  2001. TRACE_VERB("%!FUNC! read %ls %d", CVY_NAME_NBT_SUPPORT, paramp -> i_nbt_support);
  2002. TraceMsg(L"#### ParamReadAnswerFile read %ls %d\n", CVY_NAME_NBT_SUPPORT, paramp -> i_nbt_support);
  2003. }
  2004. else
  2005. {
  2006. TRACE_CRIT("%!FUNC! failed reading %ls. Retrieved %d", CVY_NAME_NBT_SUPPORT, paramp -> i_nbt_support);
  2007. }
  2008. hr = caf.HrGetDword(answer_sections, CVY_NAME_MCAST_SUPPORT, & dword);
  2009. if (SUCCEEDED(hr)) {
  2010. paramp -> mcast_support = dword;
  2011. TRACE_VERB("%!FUNC! read %ls %d", CVY_NAME_MCAST_SUPPORT, paramp -> mcast_support);
  2012. TraceMsg(L"#### ParamReadAnswerFile read %ls %d\n", CVY_NAME_MCAST_SUPPORT, paramp -> mcast_support);
  2013. }
  2014. else
  2015. {
  2016. TRACE_CRIT("%!FUNC! failed reading %ls. Retrieved %d", CVY_NAME_MCAST_SUPPORT, paramp -> mcast_support);
  2017. }
  2018. hr = caf.HrGetDword(answer_sections, CVY_NAME_MCAST_SPOOF, & dword);
  2019. if (SUCCEEDED(hr)) {
  2020. paramp -> i_mcast_spoof = dword;
  2021. TRACE_VERB("%!FUNC! read %ls %d", CVY_NAME_MCAST_SPOOF, paramp -> i_mcast_spoof);
  2022. TraceMsg(L"#### ParamReadAnswerFile read %ls %d\n", CVY_NAME_MCAST_SPOOF, paramp -> i_mcast_spoof);
  2023. }
  2024. else
  2025. {
  2026. TRACE_CRIT("%!FUNC! failed reading %ls. Retrieved %d", CVY_NAME_MCAST_SPOOF, paramp -> i_mcast_spoof);
  2027. }
  2028. hr = caf.HrGetDword(answer_sections, CVY_NAME_MASK_SRC_MAC, & dword);
  2029. if (SUCCEEDED(hr)) {
  2030. paramp -> mask_src_mac = dword;
  2031. TRACE_VERB("%!FUNC! read %ls %d", CVY_NAME_MASK_SRC_MAC, paramp -> mask_src_mac);
  2032. TraceMsg(L"#### ParamReadAnswerFile read %ls %d\n", CVY_NAME_MASK_SRC_MAC, paramp -> mask_src_mac);
  2033. }
  2034. else
  2035. {
  2036. TRACE_CRIT("%!FUNC! failed reading %ls. Retrieved %d", CVY_NAME_MASK_SRC_MAC, paramp -> mask_src_mac);
  2037. }
  2038. hr = caf.HrGetDword(answer_sections, CVY_NAME_NETMON_ALIVE, & dword);
  2039. if (SUCCEEDED(hr)) {
  2040. paramp -> i_netmon_alive = dword;
  2041. TRACE_VERB("%!FUNC! read %ls %d", CVY_NAME_NETMON_ALIVE, paramp -> i_netmon_alive);
  2042. TraceMsg(L"#### ParamReadAnswerFile read %ls %d\n", CVY_NAME_NETMON_ALIVE, paramp -> i_netmon_alive);
  2043. }
  2044. else
  2045. {
  2046. TRACE_CRIT("%!FUNC! failed reading %ls. Retrieved %d", CVY_NAME_NETMON_ALIVE, paramp -> i_netmon_alive);
  2047. }
  2048. hr = caf.HrGetDword(answer_sections, CVY_NAME_IP_CHG_DELAY, & dword);
  2049. if (SUCCEEDED(hr)) {
  2050. paramp -> i_ip_chg_delay = dword;
  2051. TRACE_VERB("%!FUNC! read %ls %d", CVY_NAME_IP_CHG_DELAY, paramp -> i_ip_chg_delay);
  2052. TraceMsg(L"#### ParamReadAnswerFile read %ls %d\n", CVY_NAME_IP_CHG_DELAY, paramp -> i_ip_chg_delay);
  2053. }
  2054. else
  2055. {
  2056. TRACE_CRIT("%!FUNC! failed reading %ls. Retrieved %d", CVY_NAME_IP_CHG_DELAY, paramp -> i_ip_chg_delay);
  2057. }
  2058. hr = caf.HrGetDword(answer_sections, CVY_NAME_CONVERT_MAC, & dword);
  2059. if (SUCCEEDED(hr)) {
  2060. paramp -> i_convert_mac = dword;
  2061. TRACE_VERB("%!FUNC! read %ls %d", CVY_NAME_CONVERT_MAC, paramp -> i_convert_mac);
  2062. TraceMsg(L"#### ParamReadAnswerFile read %ls %d\n", CVY_NAME_CONVERT_MAC, paramp -> i_convert_mac);
  2063. }
  2064. else
  2065. {
  2066. TRACE_CRIT("%!FUNC! failed reading %ls. Retrieved %d", CVY_NAME_CONVERT_MAC, paramp -> i_convert_mac);
  2067. }
  2068. hr = caf.HrGetString(answer_sections, CVY_NAME_LICENSE_KEY, & str);
  2069. if (SUCCEEDED(hr)) {
  2070. wcsncpy(paramp -> i_license_key, str.c_str(), wcslen(str.c_str()) > sizeof (paramp -> i_license_key) - sizeof (WCHAR) ?
  2071. sizeof (paramp -> i_license_key) - sizeof (WCHAR) : wcslen(str.c_str()) + 1);
  2072. TRACE_VERB("%!FUNC! read %ls %ls", CVY_NAME_LICENSE_KEY, paramp -> i_license_key);
  2073. TraceMsg(L"#### ParamReadAnswerFile read %ls %ls\n", CVY_NAME_LICENSE_KEY, paramp -> i_license_key);
  2074. }
  2075. else
  2076. {
  2077. TRACE_CRIT("%!FUNC! failed reading %ls.", CVY_NAME_LICENSE_KEY);
  2078. }
  2079. hr = caf.HrGetDword(answer_sections, CVY_NAME_RMT_PASSWORD, & dword);
  2080. if (SUCCEEDED(hr)) {
  2081. paramp -> i_rmt_password = dword;
  2082. TRACE_VERB("%!FUNC! read %ls %x", CVY_NAME_RMT_PASSWORD, paramp -> i_rmt_password);
  2083. TraceMsg(L"#### ParamReadAnswerFile read %ls %x\n", CVY_NAME_RMT_PASSWORD, paramp -> i_rmt_password);
  2084. }
  2085. else
  2086. {
  2087. TRACE_CRIT("%!FUNC! failed reading %ls. Retrieved %x", CVY_NAME_RMT_PASSWORD, paramp -> i_rmt_password);
  2088. }
  2089. hr = caf.HrGetDword(answer_sections, CVY_NAME_RCT_PASSWORD, & dword);
  2090. if (SUCCEEDED(hr)) {
  2091. paramp -> i_rct_password = dword;
  2092. TRACE_VERB("%!FUNC! read %ls %x", CVY_NAME_RCT_PASSWORD, paramp -> i_rct_password);
  2093. TraceMsg(L"#### ParamReadAnswerFile read %ls %x\n", CVY_NAME_RCT_PASSWORD, paramp -> i_rct_password);
  2094. }
  2095. else
  2096. {
  2097. TRACE_CRIT("%!FUNC! failed reading %ls. Retrieved %x", CVY_NAME_RCT_PASSWORD, paramp -> i_rct_password);
  2098. }
  2099. hr = caf.HrGetDword(answer_sections, CVY_NAME_RCT_PORT, & dword);
  2100. if (SUCCEEDED(hr)) {
  2101. paramp -> rct_port = dword;
  2102. TRACE_VERB("%!FUNC! read %ls %d", CVY_NAME_RCT_PORT, paramp -> rct_port);
  2103. TraceMsg(L"#### ParamReadAnswerFile read %ls %d\n", CVY_NAME_RCT_PORT, paramp -> rct_port);
  2104. }
  2105. else
  2106. {
  2107. TRACE_CRIT("%!FUNC! failed reading %ls. Retrieved %d", CVY_NAME_RCT_PORT, paramp -> rct_port);
  2108. }
  2109. hr = caf.HrGetDword(answer_sections, CVY_NAME_RCT_ENABLED, & dword);
  2110. if (SUCCEEDED(hr)) {
  2111. paramp -> rct_enabled = dword;
  2112. TRACE_VERB("%!FUNC! read %ls %d", CVY_NAME_RCT_ENABLED, paramp -> rct_enabled);
  2113. TraceMsg(L"#### ParamReadAnswerFile read %ls %d\n", CVY_NAME_RCT_ENABLED, paramp -> rct_enabled);
  2114. }
  2115. else
  2116. {
  2117. TRACE_CRIT("%!FUNC! failed reading %ls. Retrieved %d", CVY_NAME_RCT_ENABLED, paramp -> rct_enabled);
  2118. }
  2119. hr = caf.HrGetString(answer_sections, CVY_NAME_PASSWORD, & str);
  2120. if (SUCCEEDED(hr)) {
  2121. WCHAR passw [LICENSE_STR_IMPORTANT_CHARS + 1];
  2122. wcsncpy(passw, str.c_str(), wcslen(str.c_str()) > sizeof (passw) - sizeof (WCHAR) ?
  2123. sizeof (passw) - sizeof (WCHAR) : wcslen(str.c_str()) + 1);
  2124. paramp -> i_rct_password = License_wstring_encode (passw);
  2125. TRACE_VERB("%!FUNC! read %ls %ls %x", CVY_NAME_PASSWORD, passw, paramp -> i_rct_password);
  2126. TraceMsg(TEXT("#### ParamReadAnswerFile read %ls %ls %x\n"), CVY_NAME_PASSWORD, passw, paramp -> i_rct_password);
  2127. }
  2128. else
  2129. {
  2130. TRACE_CRIT("%!FUNC! failed reading %ls.", CVY_NAME_PASSWORD);
  2131. }
  2132. /* IGMP support. */
  2133. hr = caf.HrGetDword(answer_sections, CVY_NAME_IGMP_SUPPORT, &dword);
  2134. if (SUCCEEDED(hr)) {
  2135. paramp->fIGMPSupport = dword;
  2136. TRACE_VERB("%!FUNC! read %ls %d", CVY_NAME_IGMP_SUPPORT, paramp->fIGMPSupport);
  2137. TraceMsg(L"#### ParamReadAnswerFile read %ls %d\n", CVY_NAME_IGMP_SUPPORT, paramp->fIGMPSupport);
  2138. }
  2139. else
  2140. {
  2141. TRACE_CRIT("%!FUNC! failed reading %ls. Retrieved %d", CVY_NAME_IGMP_SUPPORT, paramp->fIGMPSupport);
  2142. }
  2143. hr = caf.HrGetDword(answer_sections, CVY_NAME_IP_TO_MCASTIP, &dword);
  2144. if (SUCCEEDED(hr)) {
  2145. paramp->fIpToMCastIp = dword;
  2146. TRACE_VERB("%!FUNC! read %ls %d", CVY_NAME_IP_TO_MCASTIP, paramp->fIpToMCastIp);
  2147. TraceMsg(L"#### ParamReadAnswerFile read %ls %d\n", CVY_NAME_IP_TO_MCASTIP, paramp->fIpToMCastIp);
  2148. }
  2149. else
  2150. {
  2151. TRACE_CRIT("%!FUNC! failed reading %ls. Retrieved %d", CVY_NAME_IP_TO_MCASTIP, paramp->fIpToMCastIp);
  2152. }
  2153. hr = caf.HrGetString(answer_sections, CVY_NAME_MCAST_IP_ADDR, &str);
  2154. if (SUCCEEDED(hr)) {
  2155. wcsncpy(paramp->szMCastIpAddress, str.c_str(), wcslen(str.c_str()) > sizeof(paramp->szMCastIpAddress) - sizeof(WCHAR) ?
  2156. sizeof(paramp->szMCastIpAddress) - sizeof(WCHAR) : wcslen(str.c_str()) + 1);
  2157. TRACE_VERB("%!FUNC! read %ls %ls", CVY_NAME_MCAST_IP_ADDR, paramp->szMCastIpAddress);
  2158. TraceMsg(L"#### ParamReadAnswerFile read %ls %ls\n", CVY_NAME_MCAST_IP_ADDR, paramp->szMCastIpAddress);
  2159. }
  2160. else
  2161. {
  2162. TRACE_CRIT("%!FUNC! failed reading %ls.", CVY_NAME_MCAST_IP_ADDR);
  2163. }
  2164. /* End IGMP support. */
  2165. hr = HrSetupGetFirstMultiSzFieldWithAlloc(caf.Hinf(), answer_sections, CVY_NAME_PORTS, & port_str);
  2166. if (SUCCEEDED(hr)) {
  2167. PWCHAR ptr;
  2168. PWLBS_PORT_RULE rp, rulep;
  2169. /* distinct rule elements for parsing */
  2170. typedef enum
  2171. {
  2172. vip,
  2173. start,
  2174. end,
  2175. protocol,
  2176. mode,
  2177. affinity,
  2178. load,
  2179. priority
  2180. }
  2181. CVY_RULE_ELEMENT;
  2182. CVY_RULE_ELEMENT elem = vip;
  2183. DWORD count = 0;
  2184. DWORD i;
  2185. DWORD dwVipLen = 0;
  2186. const DWORD dwVipAllNameLen = sizeof(CVY_NAME_PORTRULE_VIPALL)/sizeof(WCHAR) - 1; // Used below in a loop. Set it here since it is a constant.
  2187. WCHAR wszTraceOutputTmp[WLBS_MAX_CL_IP_ADDR + 1];
  2188. bool bFallThrough = false; // Used in 'vip' case statement below.
  2189. ptr = port_str;
  2190. TRACE_VERB("%!FUNC! %ls", ptr);
  2191. TraceMsg(L"%ls\n", ptr);
  2192. while (!(*ptr == 0 && *(ptr+1) == 0)) {
  2193. if (*ptr == 0) {
  2194. *ptr = L',';
  2195. TRACE_VERB("%!FUNC! %ls", ptr);
  2196. TraceMsg(L"%ls\n", ptr);
  2197. }
  2198. ptr++;
  2199. }
  2200. TRACE_VERB("%!FUNC! read %ls %ls", CVY_NAME_PORTS, port_str);
  2201. TraceMsg(L"#### ParamReadAnswerFile read %ls %ls\n", CVY_NAME_PORTS, port_str);
  2202. rulep = paramp->i_port_rules;
  2203. ptr = port_str;
  2204. while (ptr != NULL) {
  2205. switch (elem) {
  2206. case vip:
  2207. // DO NOT MOVE THIS CASE STATEMENT. IT MUST ALWAYS COME BEFORE THE 'start' CASE STATEMENT. See FALLTHROUGH comment below.
  2208. bFallThrough = false;
  2209. dwVipLen = 0;
  2210. if (ValidateVipInRule(ptr, L',', dwVipLen))
  2211. {
  2212. ASSERT(dwVipLen <= WLBS_MAX_CL_IP_ADDR);
  2213. // rulep->virtual_ip_addr is a TCHAR and ptr is a WCHAR.
  2214. // Data is moved from the latter to the former so ASSERT TCHAR is WCHAR.
  2215. ASSERT(sizeof(TCHAR) == sizeof(WCHAR));
  2216. // This is a rule for a specific VIP
  2217. _tcsncpy(rulep->virtual_ip_addr, ptr, dwVipLen);
  2218. (rulep->virtual_ip_addr)[dwVipLen] = '\0';
  2219. }
  2220. else
  2221. {
  2222. // This is either an 'all' rule, a VIP-less rule or a malformed rule. We can't distinguish a malformed rule
  2223. // from a VIP-less rule, so we will assume the rule is either an 'all' rule or a VIP-less rule. In both cases
  2224. // set the VIP component of the rule to be the default or 'all' value.
  2225. // Copy the 'all' IP into the rule.
  2226. _tcscpy(rulep->virtual_ip_addr, CVY_DEF_ALL_VIP);
  2227. if (dwVipAllNameLen != dwVipLen || (_tcsnicmp(ptr, CVY_NAME_PORTRULE_VIPALL, dwVipAllNameLen) != 0))
  2228. {
  2229. // The rule is either VIP-less or it is malformed. We assume it is VIP-less and let the 'start'
  2230. // case handle the current token as a start_port property by falling through to the next case clause
  2231. // rather than breaking.
  2232. bFallThrough = true;
  2233. _tcsncpy(wszTraceOutputTmp, ptr, dwVipLen);
  2234. wszTraceOutputTmp[dwVipLen] = '\0';
  2235. TRACE_VERB("%!FUNC! VIP element of port rule is invalid = %ls", wszTraceOutputTmp);
  2236. TraceMsg(L"-----\n#### VIP element of port rule is invalid = %s\n", wszTraceOutputTmp);
  2237. }
  2238. }
  2239. TRACE_VERB("%!FUNC! Port rule vip = %ls", rulep->virtual_ip_addr);
  2240. TraceMsg(L"-----\n#### Port rule vip = %s\n", rulep->virtual_ip_addr);
  2241. elem = start;
  2242. // !!!!!!!!!!!!!!!!!!!!
  2243. // FALLTHROUGH
  2244. // !!!!!!!!!!!!!!!!!!!!
  2245. // When we have a VIP-less port rule, we will fall through this case statement into the 'start' case statement
  2246. // below so that the current token can be used as the start_port for a port rule.
  2247. if (!bFallThrough)
  2248. {
  2249. // We have a VIP in the port rule. We do a "break;" as std operating procedure.
  2250. TRACE_VERB("%!FUNC! Fallthrough case statement from port rule vip to start");
  2251. TraceMsg(L"-----\n#### Fallthrough case statement from port rule vip to start\n");
  2252. break;
  2253. }
  2254. // NO AUTOMATIC "break;" STATEMENT HERE. Above, we conditionally flow to the 'start' case...
  2255. case start:
  2256. // DO NOT MOVE THIS CASE STATEMENT. IT MUST ALWAYS COME AFTER THE 'vip' CASE STATEMENT.
  2257. // See comments (FALLTHROUGH) inside the 'vip' case statement.
  2258. rulep->start_port = _wtoi(ptr);
  2259. // CVY_CHECK_MIN (rulep->start_port, CVY_MIN_PORT);
  2260. CVY_CHECK_MAX (rulep->start_port, CVY_MAX_PORT);
  2261. TRACE_VERB("%!FUNC! Start port = %d", rulep->start_port);
  2262. TraceMsg(L"-----\n#### Start port = %d\n", rulep->start_port);
  2263. elem = end;
  2264. break;
  2265. case end:
  2266. rulep->end_port = _wtoi(ptr);
  2267. // CVY_CHECK_MIN (rulep->end_port, CVY_MIN_PORT);
  2268. CVY_CHECK_MAX (rulep->end_port, CVY_MAX_PORT);
  2269. TRACE_VERB("%!FUNC! End port = %d", rulep->end_port);
  2270. TraceMsg(L"#### End port = %d\n", rulep->end_port);
  2271. elem = protocol;
  2272. break;
  2273. case protocol:
  2274. switch (ptr [0]) {
  2275. case L'T':
  2276. case L't':
  2277. rulep->protocol = CVY_TCP;
  2278. TRACE_VERB("%!FUNC! Protocol = TCP");
  2279. TraceMsg(L"#### Protocol = TCP\n");
  2280. break;
  2281. case L'U':
  2282. case L'u':
  2283. rulep->protocol = CVY_UDP;
  2284. TRACE_VERB("%!FUNC! Protocol = UDP");
  2285. TraceMsg(L"#### Protocol = UDP\n");
  2286. break;
  2287. default:
  2288. rulep->protocol = CVY_TCP_UDP;
  2289. TRACE_VERB("%!FUNC! Protocol = Both");
  2290. TraceMsg(L"#### Protocol = Both\n");
  2291. break;
  2292. }
  2293. elem = mode;
  2294. break;
  2295. case mode:
  2296. switch (ptr [0]) {
  2297. case L'D':
  2298. case L'd':
  2299. rulep->mode = CVY_NEVER;
  2300. TRACE_VERB("%!FUNC! Mode = Disabled");
  2301. TraceMsg(L"#### Mode = Disabled\n");
  2302. goto end_rule;
  2303. case L'S':
  2304. case L's':
  2305. rulep->mode = CVY_SINGLE;
  2306. TRACE_VERB("%!FUNC! Mode = Single");
  2307. TraceMsg(L"#### Mode = Single\n");
  2308. elem = priority;
  2309. break;
  2310. default:
  2311. rulep->mode = CVY_MULTI;
  2312. TRACE_VERB("%!FUNC! Mode = Multiple");
  2313. TraceMsg(L"#### Mode = Multiple\n");
  2314. elem = affinity;
  2315. break;
  2316. }
  2317. break;
  2318. case affinity:
  2319. switch (ptr [0]) {
  2320. case L'C':
  2321. case L'c':
  2322. rulep->mode_data.multi.affinity = CVY_AFFINITY_CLASSC;
  2323. TRACE_VERB("%!FUNC! Affinity = Class C");
  2324. TraceMsg(L"#### Affinity = Class C\n");
  2325. break;
  2326. case L'N':
  2327. case L'n':
  2328. rulep->mode_data.multi.affinity = CVY_AFFINITY_NONE;
  2329. TRACE_VERB("%!FUNC! Affinity = None");
  2330. TraceMsg(L"#### Affinity = None\n");
  2331. break;
  2332. default:
  2333. rulep->mode_data.multi.affinity = CVY_AFFINITY_SINGLE;
  2334. TRACE_VERB("%!FUNC! Affinity = Single");
  2335. TraceMsg(L"#### Affinity = Single\n");
  2336. break;
  2337. }
  2338. elem = load;
  2339. break;
  2340. case load:
  2341. if (ptr [0] == L'E' || ptr [0] == L'e') {
  2342. rulep->mode_data.multi.equal_load = TRUE;
  2343. rulep->mode_data.multi.load = CVY_DEF_LOAD;
  2344. TRACE_VERB("%!FUNC! Load = Equal");
  2345. TraceMsg(L"#### Load = Equal\n");
  2346. } else {
  2347. rulep->mode_data.multi.equal_load = FALSE;
  2348. rulep->mode_data.multi.load = _wtoi(ptr);
  2349. // CVY_CHECK_MIN (rulep->mode_data.multi.load, CVY_MIN_LOAD);
  2350. CVY_CHECK_MAX (rulep->mode_data.multi.load, CVY_MAX_LOAD);
  2351. TRACE_VERB("%!FUNC! Load = %d", rulep->mode_data.multi.load);
  2352. TraceMsg(L"#### Load = %d\n", rulep->mode_data.multi.load);
  2353. }
  2354. goto end_rule;
  2355. case priority:
  2356. rulep->mode_data.single.priority = _wtoi(ptr);
  2357. CVY_CHECK_MIN (rulep->mode_data.single.priority, CVY_MIN_PRIORITY);
  2358. CVY_CHECK_MAX (rulep->mode_data.single.priority, CVY_MAX_PRIORITY);
  2359. TRACE_VERB("%!FUNC! Priority = %d", rulep->mode_data.single.priority);
  2360. TraceMsg(L"#### Priority = %d\n", rulep->mode_data.single.priority);
  2361. goto end_rule;
  2362. default:
  2363. TRACE_VERB("%!FUNC! Bad rule element %d", elem);
  2364. TraceMsg(L"#### Bad rule element %d\n", elem);
  2365. break;
  2366. }
  2367. next_field:
  2368. ptr = wcschr(ptr, L',');
  2369. if (ptr != NULL) {
  2370. ptr ++;
  2371. continue;
  2372. } else break;
  2373. end_rule:
  2374. elem = vip;
  2375. for (i = 0; i < count; i ++) {
  2376. rp = paramp->i_port_rules + i;
  2377. if ((rulep -> start_port < rp -> start_port &&
  2378. rulep -> end_port >= rp -> start_port) ||
  2379. (rulep -> start_port >= rp -> start_port &&
  2380. rulep -> start_port <= rp -> end_port)) {
  2381. TRACE_VERB("%!FUNC! Rule %d (%d - %d) overlaps with rule %d (%d - %d)", i, rp -> start_port, rp -> end_port, count, rulep -> start_port, rulep -> end_port);
  2382. TraceMsg(L"#### Rule %d (%d - %d) overlaps with rule %d (%d - %d)\n", i, rp -> start_port, rp -> end_port, count, rulep -> start_port, rulep -> end_port);
  2383. break;
  2384. }
  2385. }
  2386. rulep -> valid = TRUE;
  2387. CVY_RULE_CODE_SET (rulep);
  2388. if (i >= count) {
  2389. count++;
  2390. rulep++;
  2391. if (count >= CVY_MAX_RULES) break;
  2392. }
  2393. goto next_field;
  2394. }
  2395. TRACE_VERB("%!FUNC! Port rules = %d", count);
  2396. TraceMsg(L"-----\n#### Port rules = %d\n", count);
  2397. paramp->i_num_rules = count;
  2398. delete [] port_str;
  2399. }
  2400. else
  2401. {
  2402. TRACE_CRIT("%!FUNC! failed reading %ls.", CVY_NAME_MCAST_IP_ADDR);
  2403. }
  2404. hr = caf.HrGetDword(answer_sections, CVY_NAME_NUM_RULES, & dword);
  2405. if (SUCCEEDED(hr)) {
  2406. paramp -> i_num_rules = dword;
  2407. TRACE_VERB("%!FUNC! read %ls %d", CVY_NAME_NUM_RULES, paramp -> i_num_rules);
  2408. TraceMsg(L"#### ParamReadAnswerFile read %ls %d\n", CVY_NAME_NUM_RULES, paramp -> i_num_rules);
  2409. }
  2410. else
  2411. {
  2412. TRACE_CRIT("%!FUNC! failed reading %ls. Retrieved %d", CVY_NAME_NUM_RULES, paramp -> i_num_rules);
  2413. }
  2414. WLBS_OLD_PORT_RULE old_port_rules [WLBS_MAX_RULES];
  2415. hr = HrSetupFindFirstLine (caf.Hinf(), answer_sections, CVY_NAME_OLD_PORT_RULES, & ctx);
  2416. if (SUCCEEDED(hr)) {
  2417. // hr = HrSetupGetBinaryField (ctx, 1, (PBYTE) paramp -> i_port_rules, sizeof (paramp -> i_port_rules), & dword);
  2418. hr = HrSetupGetBinaryField (ctx, 1, (PBYTE) old_port_rules, sizeof (old_port_rules), & dword);
  2419. if (SUCCEEDED(hr)) {
  2420. TRACE_VERB("%!FUNC! read %ls %d", CVY_NAME_OLD_PORT_RULES, dword);
  2421. TraceMsg(L"#### ParamReadAnswerFile read %ls %d\n", CVY_NAME_OLD_PORT_RULES, dword);
  2422. if (dword % sizeof (WLBS_OLD_PORT_RULE) != 0 ||
  2423. paramp -> i_num_rules != dword / sizeof (WLBS_OLD_PORT_RULE)) {
  2424. TRACE_VERB("%!FUNC! bad port rules length %d %d %d", paramp -> i_num_rules, sizeof (WLBS_OLD_PORT_RULE), dword);
  2425. TraceMsg(L"#### ParamReadAnswerFile bad port rules length %d %d %d\n", paramp -> i_num_rules, sizeof (WLBS_OLD_PORT_RULE), dword),
  2426. paramp -> i_num_rules = 0;
  2427. }
  2428. else // Convert the port rules to new format
  2429. {
  2430. if (paramp -> i_parms_ver > 3)
  2431. {
  2432. TransformOldPortRulesToNew(old_port_rules, paramp -> i_port_rules, paramp -> i_num_rules); // Returns void
  2433. TRACE_INFO("%!FUNC! transformed binary port rules to current format");
  2434. }
  2435. else
  2436. {
  2437. TRACE_INFO("%!FUNC! will not transform port rules to current format because param version is <=3: %d", paramp -> i_parms_ver);
  2438. }
  2439. }
  2440. }
  2441. else
  2442. {
  2443. paramp -> i_num_rules = 0;
  2444. TRACE_CRIT("%!FUNC! failed retrieve of binary port rules %ls while reading %d", CVY_NAME_OLD_PORT_RULES, dword);
  2445. }
  2446. }
  2447. else // Did the answer file contain port rules in the non-binary form and ParametersVersion <= 3 ?
  2448. {
  2449. if ((paramp -> i_parms_ver <= 3) && (paramp -> i_num_rules > 0))
  2450. {
  2451. TRACE_VERB("%!FUNC! Answer file contains port rules in the non-binary format and yet the version number is <=3, Assuming default port rule");
  2452. TraceMsg(L"#### ParamReadAnswerFile Answer file contains port rules in the non-binary format and yet the version number is <=3, Assuming default port rule\n");
  2453. paramp -> i_num_rules = 0;
  2454. }
  2455. }
  2456. /* decode port rules prior to version 3 */
  2457. if (paramp -> i_parms_ver <= 3) {
  2458. TRACE_VERB("%!FUNC! converting port rules from version <= 3");
  2459. TraceMsg(L"#### ParamReadAnswerFile converting port rules from version 3\n");
  2460. paramp -> i_parms_ver = CVY_PARAMS_VERSION;
  2461. /* decode the port rules */
  2462. if (paramp -> i_num_rules > 0)
  2463. {
  2464. if (! License_data_decode ((PCHAR) old_port_rules, paramp -> i_num_rules * sizeof (WLBS_OLD_PORT_RULE)))
  2465. {
  2466. paramp -> i_num_rules = 0;
  2467. TRACE_CRIT("%!FUNC! license data decode failed. Port rules will not be converted to new format.");
  2468. }
  2469. else
  2470. {
  2471. TransformOldPortRulesToNew(old_port_rules, paramp -> i_port_rules, paramp -> i_num_rules);
  2472. TRACE_INFO("%!FUNC! transformed port rules to current format. Old port rule version = %d", paramp -> i_parms_ver);
  2473. }
  2474. }
  2475. else
  2476. {
  2477. TRACE_INFO("%!FUNC! there were no port rules to transform");
  2478. }
  2479. }
  2480. /* upgrade port rules from params V1 to params V2 */
  2481. if (paramp -> i_parms_ver == 1) {
  2482. paramp -> i_parms_ver = CVY_PARAMS_VERSION;
  2483. TRACE_VERB("%!FUNC! converting from version 1");
  2484. TraceMsg(L"#### ParamReadAnswerFile converting from version 1\n");
  2485. /* keep multicast off by default for old users */
  2486. paramp -> mcast_support = FALSE;
  2487. for (i = 0; i < paramp -> i_num_rules; i ++) {
  2488. rp = paramp -> i_port_rules + i;
  2489. code = CVY_RULE_CODE_GET (rp);
  2490. CVY_RULE_CODE_SET (rp);
  2491. if (code != CVY_RULE_CODE_GET (rp)) {
  2492. rp -> code = code;
  2493. TRACE_INFO("%!FUNC! (early exit) port rule %d transformed to current version from version 1", i);
  2494. continue;
  2495. }
  2496. if (! rp -> valid) {
  2497. TRACE_CRIT("%!FUNC! port rule %d (version 1 format) is not valid and will be skipped", i);
  2498. continue;
  2499. }
  2500. /* set affinity according to current ScaleSingleClient setting */
  2501. if (rp -> mode == CVY_MULTI)
  2502. rp -> mode_data . multi . affinity = CVY_AFFINITY_SINGLE - paramp -> i_scale_client;
  2503. CVY_RULE_CODE_SET (rp);
  2504. TRACE_INFO("%!FUNC! port rule %d transformed to current version from version 1", i);
  2505. }
  2506. }
  2507. /* upgrade max number of descriptor allocs */
  2508. if (paramp -> i_parms_ver == 2) {
  2509. TRACE_VERB("%!FUNC! upgrading descriptor settings from version 2 parameters to current");
  2510. TraceMsg(L"#### ParamReadAnswerFile converting port rules from version 2\n");
  2511. paramp -> i_parms_ver = CVY_PARAMS_VERSION;
  2512. paramp -> max_dscr_allocs = CVY_DEF_MAX_DSCR_ALLOCS;
  2513. paramp -> dscr_per_alloc = CVY_DEF_DSCR_PER_ALLOC;
  2514. }
  2515. paramp -> i_max_hosts = CVY_MAX_HOSTS;
  2516. paramp -> i_max_rules = CVY_MAX_USABLE_RULES;
  2517. // CVY_CHECK_MIN (paramp -> i_num_rules, CVY_MIN_NUM_RULES);
  2518. CVY_CHECK_MAX (paramp -> i_num_rules, CVY_MAX_NUM_RULES);
  2519. CVY_CHECK_MIN (paramp -> host_priority, CVY_MIN_HOST_PRIORITY);
  2520. CVY_CHECK_MAX (paramp -> host_priority, CVY_MAX_HOST_PRIORITY);
  2521. TRACE_VERB("<-%!FUNC!");
  2522. return S_OK;
  2523. }
  2524. //+----------------------------------------------------------------------------
  2525. //
  2526. // Function: RemoveAllPortRules
  2527. //
  2528. // Description: Remove all port rules from PWLBS_REG_PARAMS
  2529. //
  2530. // Arguments: PWLBS_REG_PARAMS reg_data -
  2531. //
  2532. // Returns: Nothing
  2533. //
  2534. // History: fengsun Created Header 3/2/00
  2535. //
  2536. //+----------------------------------------------------------------------------
  2537. void RemoveAllPortRules(PWLBS_REG_PARAMS reg_data) {
  2538. TRACE_VERB("->%!FUNC!");
  2539. TraceMsg(L"RemoveAllPortRules");
  2540. reg_data -> i_num_rules = 0;
  2541. ZeroMemory(reg_data -> i_port_rules, sizeof(reg_data -> i_port_rules));
  2542. TRACE_VERB("<-%!FUNC!");
  2543. }
  2544. //+----------------------------------------------------------------------------
  2545. //
  2546. // Function: GetAdapterFromGuid
  2547. //
  2548. // Description:
  2549. //
  2550. // Arguments: INetCfg *pNetCfg -
  2551. // const GUID& NetCardGuid -
  2552. // OUT INetCfgComponent** ppNetCardComponent -
  2553. //
  2554. // Returns: HRESULT -
  2555. //
  2556. // History: fengsun Created Header 1/21/00
  2557. //
  2558. //+----------------------------------------------------------------------------
  2559. HRESULT GetAdapterFromGuid(INetCfg *pNetCfg, const GUID& NetCardGuid, OUT INetCfgComponent** ppNetCardComponent) {
  2560. TRACE_VERB("->%!FUNC!");
  2561. *ppNetCardComponent = NULL;
  2562. HRESULT hr = S_OK;
  2563. INetCfgClass *pNetCfgClass = NULL;
  2564. BOOL fFoundMatch = FALSE;
  2565. hr = pNetCfg->QueryNetCfgClass(&GUID_DEVCLASS_NET, IID_INetCfgClass, (void **)&pNetCfgClass);
  2566. if (FAILED(hr)) {
  2567. TraceError("INetCfg::QueryNetCfgClass failed", hr);
  2568. TRACE_CRIT("%!FUNC! QueryNetCfgClass failed with %d", hr);
  2569. return hr;
  2570. }
  2571. /* Get an enumerator to list all network devices. */
  2572. IEnumNetCfgComponent *pIEnumComponents = NULL;
  2573. if (FAILED(hr = pNetCfgClass->EnumComponents(&pIEnumComponents))) {
  2574. TraceError("INetCfg::EnumComponents failed", hr);
  2575. TRACE_CRIT("%!FUNC! failed enumerating components with %d", hr);
  2576. pNetCfgClass->Release();
  2577. return hr;
  2578. }
  2579. /* Go through all the components and bind to the matching netcard. */
  2580. while (pIEnumComponents->Next(1, ppNetCardComponent, NULL) == S_OK) {
  2581. GUID guidInstance;
  2582. /* Retrieve the instance GUID of the component. */
  2583. if (FAILED(hr = (*ppNetCardComponent)->GetInstanceGuid(&guidInstance))) {
  2584. TraceError("GetInstanceGuid failed", hr);
  2585. TRACE_CRIT("%!FUNC! getting instance guid from the net card failed with %d", hr);
  2586. continue;
  2587. }
  2588. /* Check whether we found a match. */
  2589. if (IsEqualGUID(NetCardGuid, guidInstance)) {
  2590. fFoundMatch = TRUE;
  2591. TRACE_INFO("%!FUNC! netcard matched to component");
  2592. break;
  2593. }
  2594. (*ppNetCardComponent)->Release();
  2595. *ppNetCardComponent = NULL;
  2596. }
  2597. if (!fFoundMatch) {
  2598. TraceMsg(L"Found no netcard\n");
  2599. TRACE_CRIT("%!FUNC! no adapter found with the input GUID");
  2600. hr = HRESULT_FROM_WIN32( ERROR_NOT_FOUND );
  2601. }
  2602. if (pIEnumComponents) pIEnumComponents->Release();
  2603. if (pNetCfgClass) pNetCfgClass->Release();
  2604. TRACE_VERB("<-%!FUNC!");
  2605. return hr;
  2606. }
  2607. //+----------------------------------------------------------------------------
  2608. //
  2609. // Function: WriteAdapterName
  2610. //
  2611. // Description:
  2612. //
  2613. // Arguments: CWlbsConfig* pConfig -
  2614. // GUID& AdapterGuid -
  2615. //
  2616. // Returns: bool -
  2617. //
  2618. // History: fengsun Created Header 7/6/00
  2619. //
  2620. //+----------------------------------------------------------------------------
  2621. bool WriteAdapterName(CWlbsConfig* pConfig, GUID& AdapterGuid) {
  2622. TRACE_VERB("->%!FUNC!");
  2623. PWSTR pszPnpDevNodeId = NULL;
  2624. HKEY key;
  2625. DWORD status;
  2626. HRESULT hr;
  2627. INetCfgComponent* pAdapter = NULL;
  2628. hr = GetAdapterFromGuid(pConfig->m_pNetCfg, AdapterGuid, &pAdapter);
  2629. if (hr != S_OK) {
  2630. TraceError("GetAdapterFromGuid failed at GetPnpDevNodeId", hr);
  2631. TRACE_CRIT("%!FUNC! GetAdapterFromGuid failed with %d", hr);
  2632. TRACE_VERB("<-%!FUNC!");
  2633. return false;
  2634. }
  2635. hr = pAdapter->GetPnpDevNodeId (& pszPnpDevNodeId);
  2636. pAdapter->Release();
  2637. pAdapter = NULL;
  2638. if (hr != S_OK) {
  2639. TraceError("HrWriteAdapterName failed at GetPnpDevNodeId", hr);
  2640. TRACE_CRIT("%!FUNC! GetPnpDevNodeId on adapter failed with %d", hr);
  2641. TRACE_VERB("<-%!FUNC!");
  2642. return false;
  2643. }
  2644. key = pConfig->m_pWlbsApiFuncs->pfnRegOpenWlbsSetting(AdapterGuid, false);
  2645. if (key == NULL) {
  2646. status = GetLastError();
  2647. TraceError("HrWriteAdapterName failed at RegOpenWlbsSetting", status);
  2648. CoTaskMemFree(pszPnpDevNodeId);
  2649. TRACE_CRIT("%!FUNC! RegOpenWlbsSetting failed with %d", status);
  2650. TRACE_VERB("<-%!FUNC!");
  2651. return false;
  2652. }
  2653. status = RegSetValueEx (key, CVY_NAME_CLUSTER_NIC, 0L, CVY_TYPE_CLUSTER_NIC, (LPBYTE) pszPnpDevNodeId, wcslen(pszPnpDevNodeId) * sizeof (WCHAR));
  2654. CoTaskMemFree(pszPnpDevNodeId);
  2655. RegCloseKey(key);
  2656. if (status != ERROR_SUCCESS) {
  2657. TraceError("HrWriteAdapterName failed at RegSetValueEx", status);
  2658. TRACE_CRIT("%!FUNC! RegSetValueEx failed with %d", status);
  2659. TRACE_VERB("<-%!FUNC!");
  2660. return false;
  2661. }
  2662. TRACE_VERB("<-%!FUNC!");
  2663. return true;
  2664. }
  2665. //+----------------------------------------------------------------------------
  2666. //
  2667. // Function: ValidateVipInRule
  2668. //
  2669. // Description: Parses pwszRuleString, looking for a valid VIP which must be
  2670. // in the first token
  2671. //
  2672. // Arguments: PWCHAR pwszRuleString - tokenized string concatentating all
  2673. // defined port rules
  2674. // PWCHAR pwToken - the token character that separates the fields
  2675. // DWORD& dwVipLen - if a token is found, this contains the size
  2676. // of the string; 0 otherwise. The number of
  2677. // characters returned is bound to <=
  2678. // WLBS_MAX_CL_IP_ADDR
  2679. //
  2680. // NOTES: A non-zero value for dwVipLen does NOT imply that the VIP is valid,
  2681. // only that there was a non-zero length string in the expected
  2682. // location. The user must check the return value to validate the VIP.
  2683. //
  2684. // Returns: bool - true if the first field in the string has a valid IP address
  2685. // format; false otherwise.
  2686. //
  2687. // Assumptions: First token is the VIP element of a port rule
  2688. //
  2689. // History: chrisdar Created 01/05/15
  2690. //
  2691. //+----------------------------------------------------------------------------
  2692. bool ValidateVipInRule(const PWCHAR pwszRuleString, const WCHAR pwToken, DWORD& dwVipLen)
  2693. {
  2694. TRACE_VERB("->%!FUNC!");
  2695. ASSERT(NULL != pwszRuleString);
  2696. bool ret = false;
  2697. dwVipLen = 0;
  2698. // Find the first occurence of the token string, which will denote the end of
  2699. // the VIP part of the rule
  2700. PWCHAR pwcAtSeparator = wcschr(pwszRuleString, pwToken);
  2701. if (NULL == pwcAtSeparator) {
  2702. TRACE_CRIT("%!FUNC! No token separator when one was expected");
  2703. TRACE_VERB("<-%!FUNC!");
  2704. return ret;
  2705. }
  2706. // Found the token string. Copy out the VIP and validate it.
  2707. WCHAR wszIP[WLBS_MAX_CL_IP_ADDR + 1];
  2708. DWORD dwStrLen = min((UINT)(pwcAtSeparator - pwszRuleString),
  2709. WLBS_MAX_CL_IP_ADDR);
  2710. wcsncpy(wszIP, pwszRuleString, dwStrLen);
  2711. wszIP[dwStrLen] = '\0';
  2712. ASSERT(dwStrLen == wcslen(wszIP));
  2713. dwVipLen = dwStrLen;
  2714. // IpAddressFromAbcdWsz calls inet_addr to check the format of the IP address, but the
  2715. // allowed formats are very flexible. For our port rule definition of a VIP we require
  2716. // a rigid a.b.c.d format. To ensure that we only say the IP address is valid for IPs
  2717. // specified in this manner, ensure that there are 3 and only 3 '.' in the string.
  2718. DWORD dwTmpCount = 0;
  2719. PWCHAR pwszTmp = pwszRuleString;
  2720. while (pwszTmp < pwcAtSeparator)
  2721. {
  2722. if (*pwszTmp++ == L'.') { dwTmpCount++; }
  2723. }
  2724. if (dwTmpCount == 3 && INADDR_NONE != IpAddressFromAbcdWsz(wszIP)) {
  2725. TRACE_INFO("%!FUNC! The IP address %ls is a valid IP of the form a.b.c.d", wszIP);
  2726. ret = true;
  2727. } else {
  2728. TRACE_INFO("%!FUNC! The IP address %ls is NOT a valid IP of the form a.b.c.d", wszIP);
  2729. }
  2730. TRACE_VERB("<-%!FUNC!");
  2731. return ret;
  2732. }