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

3941 lines
148 KiB

  1. /*++
  2. Copyright(c) 1998,99 Microsoft Corporation
  3. Module Name:
  4. params.cpp
  5. Abstract:
  6. Windows Load Balancing Service (WLBS)
  7. API - registry parameters support
  8. Author:
  9. kyrilf
  10. --*/
  11. #include "precomp.h"
  12. #include "cluster.h"
  13. #include "control.h"
  14. #include "param.h"
  15. #include "debug.h"
  16. #include "params.tmh" // for event tracing
  17. extern HINSTANCE g_hInstCtrl; // Global variable for the dll instance, defined in control.cpp
  18. HKEY WINAPI RegOpenWlbsSetting(const GUID& AdapterGuid, bool fReadOnly)
  19. {
  20. TRACE_VERB("->%!FUNC!");
  21. WCHAR reg_path [PARAMS_MAX_STRING_SIZE];
  22. WCHAR szAdapterGuid[128];
  23. HRESULT hresult;
  24. if (0 == StringFromGUID2(AdapterGuid, szAdapterGuid, sizeof(szAdapterGuid)/sizeof(szAdapterGuid[0])))
  25. {
  26. TRACE_CRIT("%!FUNC! guid is too large for string. Result is %ls", szAdapterGuid);
  27. // This check was added for tracing. No abort was done previously on error, so don't do so now.
  28. }
  29. hresult = StringCbPrintf(reg_path, sizeof(reg_path), L"SYSTEM\\CurrentControlSet\\Services\\WLBS\\Parameters\\Interface\\%s",
  30. szAdapterGuid);
  31. if (FAILED(hresult))
  32. {
  33. TRACE_CRIT("StringCbPrintf failed, Error code : 0x%x", HRESULT_CODE(hresult));
  34. TRACE_VERB("<-%!FUNC! handle NULL");
  35. return NULL;
  36. }
  37. HKEY hKey = NULL;
  38. DWORD dwRet = RegOpenKeyEx (HKEY_LOCAL_MACHINE, reg_path, 0L,
  39. fReadOnly? KEY_READ : KEY_WRITE, & hKey);
  40. if (dwRet != ERROR_SUCCESS)
  41. {
  42. TRACE_CRIT("%!FUNC! failed to read %ls from registry with 0x%lx", reg_path, dwRet);
  43. TRACE_VERB("<-%!FUNC! handle NULL");
  44. return NULL;
  45. }
  46. TRACE_VERB("<-%!FUNC! return valid handle");
  47. return hKey;
  48. }
  49. //+----------------------------------------------------------------------------
  50. //
  51. // Function: TransformOldPortRulesToNew
  52. //
  53. // Description: Transforms port rules contained in structures without the virtual
  54. // ip address into the new ones that do
  55. //
  56. // Arguments: Array of Old Port Rules, Array of New Port Rules, Length of Array
  57. //
  58. // Returns: void
  59. //
  60. // History: KarthicN, Created on 3/19/01
  61. //
  62. //+----------------------------------------------------------------------------
  63. void TransformOldPortRulesToNew(PWLBS_OLD_PORT_RULE p_old_port_rules,
  64. PWLBS_PORT_RULE p_new_port_rules,
  65. DWORD num_rules)
  66. {
  67. HRESULT hresult;
  68. TRACE_VERB("->%!FUNC! number of rules %d", num_rules);
  69. if (num_rules == 0)
  70. return;
  71. while(num_rules--)
  72. {
  73. hresult = StringCbCopy(p_new_port_rules->virtual_ip_addr, sizeof(p_new_port_rules->virtual_ip_addr), CVY_DEF_ALL_VIP);
  74. if (FAILED(hresult))
  75. {
  76. TRACE_CRIT("%!FUNC! string copy for vip failed, Error code : 0x%x", HRESULT_CODE(hresult));
  77. // This check was added for tracing. No abort was done previously on error, so don't do so now.
  78. }
  79. p_new_port_rules->start_port = p_old_port_rules->start_port;
  80. p_new_port_rules->end_port = p_old_port_rules->end_port;
  81. #ifdef WLBSAPI_INTERNAL_ONLY
  82. p_new_port_rules->code = p_old_port_rules->code;
  83. #else
  84. p_new_port_rules->Private1 = p_old_port_rules->Private1;
  85. #endif
  86. p_new_port_rules->mode = p_old_port_rules->mode;
  87. p_new_port_rules->protocol = p_old_port_rules->protocol;
  88. #ifdef WLBSAPI_INTERNAL_ONLY
  89. p_new_port_rules->valid = p_old_port_rules->valid;
  90. #else
  91. p_new_port_rules->Private2 = p_old_port_rules->Private2;
  92. #endif
  93. switch (p_new_port_rules->mode)
  94. {
  95. case CVY_MULTI :
  96. p_new_port_rules->mode_data.multi.equal_load = p_old_port_rules->mode_data.multi.equal_load;
  97. p_new_port_rules->mode_data.multi.affinity = p_old_port_rules->mode_data.multi.affinity;
  98. p_new_port_rules->mode_data.multi.load = p_old_port_rules->mode_data.multi.load;
  99. break;
  100. case CVY_SINGLE :
  101. p_new_port_rules->mode_data.single.priority = p_old_port_rules->mode_data.single.priority;
  102. break;
  103. default:
  104. TRACE_CRIT("%!FUNC! illegal port rule mode %d. Ignoring property...", p_new_port_rules->mode);
  105. break;
  106. }
  107. p_old_port_rules++;
  108. p_new_port_rules++;
  109. }
  110. TRACE_VERB("<-%!FUNC!");
  111. return;
  112. }
  113. /* Open the bi-directional affinity teaming registry key for a specified adapter. */
  114. HKEY WINAPI RegOpenWlbsBDASettings (const GUID& AdapterGuid, bool fReadOnly) {
  115. TRACE_VERB("->%!FUNC!");
  116. WCHAR reg_path[PARAMS_MAX_STRING_SIZE];
  117. WCHAR szAdapterGuid[128];
  118. HKEY hKey = NULL;
  119. DWORD dwRet;
  120. HRESULT hresult;
  121. if (0 == StringFromGUID2(AdapterGuid, szAdapterGuid, sizeof(szAdapterGuid)/sizeof(szAdapterGuid[0])))
  122. {
  123. TRACE_CRIT("%!FUNC! guid is too large for string. Result is %ls", szAdapterGuid);
  124. // This check was added for tracing. No abort was done previously on error, so don't do so now.
  125. }
  126. hresult = StringCbPrintf(reg_path, sizeof(reg_path), L"SYSTEM\\CurrentControlSet\\Services\\WLBS\\Parameters\\Interface\\%ls\\%ls", szAdapterGuid, CVY_NAME_BDA_TEAMING);
  127. if (FAILED(hresult))
  128. {
  129. TRACE_CRIT("StringCbPrintf failed, Error code : 0x%x", HRESULT_CODE(hresult));
  130. TRACE_VERB("<-%!FUNC! handle NULL");
  131. return NULL;
  132. }
  133. dwRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, reg_path, 0L, fReadOnly ? KEY_READ : KEY_WRITE, &hKey);
  134. //
  135. // BDA isn't typically configured so don't report not-found errors
  136. //
  137. if (dwRet != ERROR_SUCCESS) {
  138. if (dwRet != ERROR_FILE_NOT_FOUND)
  139. {
  140. TRACE_CRIT("%!FUNC! failed to read %ls from registry with 0x%lx", reg_path, dwRet);
  141. }
  142. TRACE_VERB("<-%!FUNC! handle NULL");
  143. return NULL;
  144. }
  145. TRACE_VERB("<-%!FUNC! return valid handle %p", hKey);
  146. return hKey;
  147. }
  148. /* Create the bi-directional affinity teaming registry key for a specified adapter. */
  149. HKEY WINAPI RegCreateWlbsBDASettings (const GUID& AdapterGuid) {
  150. TRACE_VERB("->%!FUNC!");
  151. WCHAR reg_path[PARAMS_MAX_STRING_SIZE];
  152. WCHAR szAdapterGuid[128];
  153. HKEY hKey = NULL;
  154. DWORD dwRet;
  155. DWORD disp;
  156. HRESULT hresult;
  157. if (0 == StringFromGUID2(AdapterGuid, szAdapterGuid, sizeof(szAdapterGuid)/sizeof(szAdapterGuid[0])))
  158. {
  159. TRACE_CRIT("%!FUNC! guid is too large for string. Result is %ls", szAdapterGuid);
  160. // This check was added for tracing. No abort was done previously on error, so don't do so now.
  161. }
  162. hresult = StringCbPrintf(reg_path, sizeof(reg_path), L"SYSTEM\\CurrentControlSet\\Services\\WLBS\\Parameters\\Interface\\%ls\\%ls", szAdapterGuid, CVY_NAME_BDA_TEAMING);
  163. if (FAILED(hresult))
  164. {
  165. TRACE_CRIT("StringCbPrintf failed, Error code : 0x%x", HRESULT_CODE(hresult));
  166. TRACE_VERB("<-%!FUNC! handle NULL");
  167. return NULL;
  168. }
  169. dwRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, reg_path, 0L, L"", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &disp);
  170. if (dwRet != ERROR_SUCCESS) {
  171. TRACE_CRIT("%!FUNC! failed to create %ls in registry with 0x%lx", reg_path, dwRet);
  172. TRACE_VERB("<-%!FUNC! handle NULL");
  173. return NULL;
  174. }
  175. TRACE_VERB("<-%!FUNC! handle");
  176. return hKey;
  177. }
  178. /* Delete the bi-directional affinity teaming registry key for a specified adapter. */
  179. bool WINAPI RegDeleteWlbsBDASettings (const GUID& AdapterGuid) {
  180. TRACE_VERB("->%!FUNC!");
  181. WCHAR reg_path[PARAMS_MAX_STRING_SIZE];
  182. WCHAR szAdapterGuid[128];
  183. DWORD dwRet;
  184. HRESULT hresult;
  185. if (0 == StringFromGUID2(AdapterGuid, szAdapterGuid, sizeof(szAdapterGuid)/sizeof(szAdapterGuid[0])))
  186. {
  187. TRACE_CRIT("%!FUNC! guid is too large for string. Result is %ls", szAdapterGuid);
  188. // This check was added for tracing. No abort was done previously on error, so don't do so now.
  189. }
  190. hresult = StringCbPrintf(reg_path, sizeof(reg_path), L"SYSTEM\\CurrentControlSet\\Services\\WLBS\\Parameters\\Interface\\%ls\\%ls", szAdapterGuid, CVY_NAME_BDA_TEAMING);
  191. if (FAILED(hresult))
  192. {
  193. TRACE_CRIT("StringCbPrintf failed, Error code : 0x%x", HRESULT_CODE(hresult));
  194. TRACE_VERB("<-%!FUNC! fail");
  195. return FALSE;
  196. }
  197. dwRet = RegDeleteKey(HKEY_LOCAL_MACHINE, reg_path);
  198. //
  199. // BDA isn't typically configured so don't report not-found errors
  200. //
  201. if (dwRet != ERROR_SUCCESS) {
  202. if (dwRet != ERROR_FILE_NOT_FOUND)
  203. {
  204. TRACE_CRIT("%!FUNC! failed to delete %ls from registry with 0x%lx", reg_path, dwRet);
  205. }
  206. TRACE_VERB("<-%!FUNC! fail");
  207. return FALSE;
  208. }
  209. TRACE_VERB("<-%!FUNC! pass");
  210. return TRUE;
  211. }
  212. //+----------------------------------------------------------------------------
  213. //
  214. // Function: WlbsParamReadReg
  215. //
  216. // Description: This function is a wrapper around ParamReadReg, created for
  217. // the sake for making it callable from 'C' modules
  218. //
  219. // Arguments: const GUID& AdapterGuid - IN, Adapter guid
  220. // PWLBS_REG_PARAMS paramp - OUT Registry parameters
  221. //
  222. // Returns: bool - true if succeeded
  223. //
  224. // History: karthicn Created Header 8/31/01
  225. //
  226. //+----------------------------------------------------------------------------
  227. BOOL WINAPI WlbsParamReadReg(const GUID * pAdapterGuid, PWLBS_REG_PARAMS paramp)
  228. {
  229. TRACE_VERB("->%!FUNC!");
  230. BOOL bRet = ParamReadReg(*pAdapterGuid, paramp);
  231. TRACE_VERB("<-%!FUNC! returning 0x%x",bRet);
  232. return bRet;
  233. }
  234. //+----------------------------------------------------------------------------
  235. //
  236. // Function: ParamReadReg
  237. //
  238. // Description: Read cluster settings from registry
  239. //
  240. // Arguments: const GUID& AdapterGuid - IN, Adapter guid
  241. // PWLBS_REG_PARAMS paramp - OUT Registry parameters
  242. // bool fUpgradeFromWin2k, whether this is a upgrade from Win2k
  243. // or earlier version
  244. //
  245. // Returns: bool - true if succeeded
  246. //
  247. // History: fengsun Created Header 3/9/00
  248. //
  249. //+----------------------------------------------------------------------------
  250. bool WINAPI ParamReadReg(const GUID& AdapterGuid,
  251. PWLBS_REG_PARAMS paramp, bool fUpgradeFromWin2k, bool *pfPortRulesInBinaryForm)
  252. {
  253. TRACE_VERB("->%!FUNC!");
  254. HKEY bda_key = NULL;
  255. HKEY key;
  256. LONG status;
  257. DWORD type;
  258. DWORD size;
  259. ULONG i, code;
  260. WLBS_PORT_RULE* rp;
  261. WCHAR reg_path [PARAMS_MAX_STRING_SIZE];
  262. HRESULT hresult;
  263. memset (paramp, 0, sizeof (*paramp));
  264. //
  265. // For win2k or NT4, only one cluster is supported, there is no per adapter settings
  266. //
  267. if (fUpgradeFromWin2k)
  268. {
  269. hresult = StringCbPrintf(reg_path, sizeof(reg_path), L"SYSTEM\\CurrentControlSet\\Services\\WLBS\\Parameters");
  270. if (FAILED(hresult))
  271. {
  272. TRACE_CRIT("StringCbPrintf failed, Error code : 0x%x", HRESULT_CODE(hresult));
  273. TRACE_VERB("<-%!FUNC! return false");
  274. return FALSE;
  275. }
  276. status = RegOpenKeyEx (HKEY_LOCAL_MACHINE, reg_path, 0L,
  277. KEY_QUERY_VALUE, & key);
  278. if (status != ERROR_SUCCESS)
  279. {
  280. TRACE_CRIT("%!FUNC! failed opening registry for %ls with 0x%lx", reg_path, status);
  281. TRACE_VERB("<-%!FUNC! return false");
  282. return false;
  283. }
  284. }
  285. else
  286. {
  287. key = RegOpenWlbsSetting(AdapterGuid, true);
  288. if (key == NULL)
  289. {
  290. TRACE_CRIT("%!FUNC! RegOpenWlbsSetting failed");
  291. TRACE_VERB("<-%!FUNC! return false");
  292. return false;
  293. }
  294. }
  295. size = sizeof (paramp -> install_date);
  296. status = RegQueryValueEx (key, CVY_NAME_INSTALL_DATE, 0L, & type,
  297. (LPBYTE) & paramp -> install_date, & size);
  298. if (status != ERROR_SUCCESS)
  299. {
  300. paramp -> install_date = 0;
  301. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using %d", CVY_NAME_INSTALL_DATE, status, (DWORD)(paramp -> install_date));
  302. }
  303. size = sizeof (paramp -> i_verify_date);
  304. status = RegQueryValueEx (key, CVY_NAME_VERIFY_DATE, 0L, & type,
  305. (LPBYTE) & paramp -> i_verify_date, & size);
  306. if (status != ERROR_SUCCESS)
  307. {
  308. paramp -> i_verify_date = 0;
  309. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using %d", CVY_NAME_VERIFY_DATE, status, paramp -> i_verify_date);
  310. }
  311. size = sizeof (paramp -> i_parms_ver);
  312. status = RegQueryValueEx (key, CVY_NAME_VERSION, 0L, & type,
  313. (LPBYTE) & paramp -> i_parms_ver, & size);
  314. if (status != ERROR_SUCCESS)
  315. {
  316. paramp -> i_parms_ver = CVY_DEF_VERSION;
  317. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using %d", CVY_NAME_VERSION, status, paramp -> i_parms_ver);
  318. }
  319. size = sizeof (paramp -> i_virtual_nic_name);
  320. status = RegQueryValueEx (key, CVY_NAME_VIRTUAL_NIC, 0L, & type,
  321. (LPBYTE) paramp -> i_virtual_nic_name, & size);
  322. if (status != ERROR_SUCCESS)
  323. {
  324. paramp -> i_virtual_nic_name [0] = 0;
  325. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using NULL.", CVY_NAME_VIRTUAL_NIC, status);
  326. }
  327. size = sizeof (paramp -> host_priority);
  328. status = RegQueryValueEx (key, CVY_NAME_HOST_PRIORITY, 0L, & type,
  329. (LPBYTE) & paramp -> host_priority, & size);
  330. if (status != ERROR_SUCCESS)
  331. {
  332. paramp -> host_priority = CVY_DEF_HOST_PRIORITY;
  333. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using %d", CVY_NAME_HOST_PRIORITY, status, paramp -> host_priority);
  334. }
  335. size = sizeof (paramp -> cluster_mode);
  336. status = RegQueryValueEx (key, CVY_NAME_CLUSTER_MODE, 0L, & type,
  337. (LPBYTE) & paramp -> cluster_mode, & size);
  338. if (status != ERROR_SUCCESS)
  339. {
  340. paramp -> cluster_mode = CVY_DEF_CLUSTER_MODE;
  341. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using %d", CVY_NAME_CLUSTER_MODE, status, paramp -> cluster_mode);
  342. }
  343. size = sizeof (paramp -> persisted_states);
  344. status = RegQueryValueEx (key, CVY_NAME_PERSISTED_STATES, 0L, & type,
  345. (LPBYTE) & paramp -> persisted_states, & size);
  346. if (status != ERROR_SUCCESS)
  347. {
  348. paramp -> persisted_states = CVY_DEF_PERSISTED_STATES;
  349. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using %d", CVY_NAME_PERSISTED_STATES, status, paramp -> persisted_states);
  350. }
  351. size = sizeof (paramp -> cl_mac_addr);
  352. status = RegQueryValueEx (key, CVY_NAME_NETWORK_ADDR, 0L, & type,
  353. (LPBYTE) paramp -> cl_mac_addr, & size);
  354. if (status != ERROR_SUCCESS)
  355. {
  356. hresult = StringCbCopy(paramp -> cl_mac_addr, sizeof(paramp -> cl_mac_addr), CVY_DEF_NETWORK_ADDR);
  357. if (FAILED(hresult))
  358. {
  359. TRACE_CRIT("%!FUNC! StringCbCopy failed, Error code : 0x%x", HRESULT_CODE(hresult));
  360. }
  361. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using %ls", CVY_NAME_NETWORK_ADDR, status, CVY_DEF_NETWORK_ADDR);
  362. }
  363. size = sizeof (paramp -> cl_ip_addr);
  364. status = RegQueryValueEx (key, CVY_NAME_CL_IP_ADDR, 0L, & type,
  365. (LPBYTE) paramp -> cl_ip_addr, & size);
  366. if (status != ERROR_SUCCESS)
  367. {
  368. hresult = StringCbCopy (paramp -> cl_ip_addr, sizeof(paramp -> cl_ip_addr), CVY_DEF_CL_IP_ADDR);
  369. if (FAILED(hresult))
  370. {
  371. TRACE_CRIT("%!FUNC! StringCbCopy failed, Error code : 0x%x", HRESULT_CODE(hresult));
  372. }
  373. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using %ls", CVY_NAME_CL_IP_ADDR, status, CVY_DEF_CL_IP_ADDR);
  374. }
  375. size = sizeof (paramp -> cl_net_mask);
  376. status = RegQueryValueEx (key, CVY_NAME_CL_NET_MASK, 0L, & type,
  377. (LPBYTE) paramp -> cl_net_mask, & size);
  378. if (status != ERROR_SUCCESS)
  379. {
  380. hresult = StringCbCopy (paramp -> cl_net_mask, sizeof(paramp -> cl_net_mask), CVY_DEF_CL_NET_MASK);
  381. if (FAILED(hresult))
  382. {
  383. TRACE_CRIT("%!FUNC! StringCbCopy failed, Error code : 0x%x", HRESULT_CODE(hresult));
  384. }
  385. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using %ls", CVY_NAME_CL_NET_MASK, status, CVY_DEF_CL_NET_MASK);
  386. }
  387. size = sizeof (paramp -> ded_ip_addr);
  388. status = RegQueryValueEx (key, CVY_NAME_DED_IP_ADDR, 0L, & type,
  389. (LPBYTE) paramp -> ded_ip_addr, & size);
  390. if (status != ERROR_SUCCESS)
  391. {
  392. hresult = StringCbCopy (paramp -> ded_ip_addr, sizeof(paramp -> ded_ip_addr), CVY_DEF_DED_IP_ADDR);
  393. if (FAILED(hresult))
  394. {
  395. TRACE_CRIT("%!FUNC! StringCbCopy failed, Error code : 0x%x", HRESULT_CODE(hresult));
  396. }
  397. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using %ls", CVY_NAME_DED_IP_ADDR, status, CVY_DEF_DED_IP_ADDR);
  398. }
  399. size = sizeof (paramp -> ded_net_mask);
  400. status = RegQueryValueEx (key, CVY_NAME_DED_NET_MASK, 0L, & type,
  401. (LPBYTE) paramp -> ded_net_mask, & size);
  402. if (status != ERROR_SUCCESS)
  403. {
  404. hresult = StringCbCopy (paramp -> ded_net_mask, sizeof(paramp -> ded_net_mask), CVY_DEF_DED_NET_MASK);
  405. if (FAILED(hresult))
  406. {
  407. TRACE_CRIT("%!FUNC! StringCbCopy failed, Error code : 0x%x", HRESULT_CODE(hresult));
  408. }
  409. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using %ls", CVY_NAME_DED_NET_MASK, status, CVY_DEF_DED_NET_MASK);
  410. }
  411. size = sizeof (paramp -> domain_name);
  412. status = RegQueryValueEx (key, CVY_NAME_DOMAIN_NAME, 0L, & type,
  413. (LPBYTE) paramp -> domain_name, & size);
  414. if (status != ERROR_SUCCESS)
  415. {
  416. hresult = StringCbCopy (paramp -> domain_name, sizeof(paramp -> domain_name), CVY_DEF_DOMAIN_NAME);
  417. if (FAILED(hresult))
  418. {
  419. TRACE_CRIT("%!FUNC! StringCbCopy failed, Error code : 0x%x", HRESULT_CODE(hresult));
  420. }
  421. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using %ls", CVY_NAME_DOMAIN_NAME, status, CVY_DEF_DOMAIN_NAME);
  422. }
  423. size = sizeof (paramp -> alive_period);
  424. status = RegQueryValueEx (key, CVY_NAME_ALIVE_PERIOD, 0L, & type,
  425. (LPBYTE) & paramp -> alive_period, & size);
  426. if (status != ERROR_SUCCESS)
  427. {
  428. paramp -> alive_period = CVY_DEF_ALIVE_PERIOD;
  429. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using %d", CVY_NAME_ALIVE_PERIOD, status, paramp -> alive_period);
  430. }
  431. size = sizeof (paramp -> alive_tolerance);
  432. status = RegQueryValueEx (key, CVY_NAME_ALIVE_TOLER, 0L, & type,
  433. (LPBYTE) & paramp -> alive_tolerance, & size);
  434. if (status != ERROR_SUCCESS)
  435. {
  436. paramp -> alive_tolerance = CVY_DEF_ALIVE_TOLER;
  437. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using %d", CVY_NAME_ALIVE_TOLER, status, paramp -> alive_tolerance);
  438. }
  439. size = sizeof (paramp -> num_actions);
  440. status = RegQueryValueEx (key, CVY_NAME_NUM_ACTIONS, 0L, & type,
  441. (LPBYTE) & paramp -> num_actions, & size);
  442. if (status != ERROR_SUCCESS)
  443. {
  444. paramp -> num_actions = CVY_DEF_NUM_ACTIONS;
  445. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using %d", CVY_NAME_NUM_ACTIONS, status, paramp -> num_actions);
  446. }
  447. size = sizeof (paramp -> num_packets);
  448. status = RegQueryValueEx (key, CVY_NAME_NUM_PACKETS, 0L, & type,
  449. (LPBYTE) & paramp -> num_packets, & size);
  450. if (status != ERROR_SUCCESS)
  451. {
  452. paramp -> num_packets = CVY_DEF_NUM_PACKETS;
  453. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using %d", CVY_NAME_NUM_PACKETS, status, paramp -> num_packets);
  454. }
  455. size = sizeof (paramp -> num_send_msgs);
  456. status = RegQueryValueEx (key, CVY_NAME_NUM_SEND_MSGS, 0L, & type,
  457. (LPBYTE) & paramp -> num_send_msgs, & size);
  458. if (status != ERROR_SUCCESS)
  459. {
  460. paramp -> num_send_msgs = CVY_DEF_NUM_SEND_MSGS;
  461. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using %d", CVY_NAME_NUM_SEND_MSGS, status, paramp -> num_send_msgs);
  462. }
  463. size = sizeof (paramp -> dscr_per_alloc);
  464. status = RegQueryValueEx (key, CVY_NAME_DSCR_PER_ALLOC, 0L, & type,
  465. (LPBYTE) & paramp -> dscr_per_alloc, & size);
  466. if (status != ERROR_SUCCESS)
  467. {
  468. paramp -> dscr_per_alloc = CVY_DEF_DSCR_PER_ALLOC;
  469. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using %d", CVY_NAME_DSCR_PER_ALLOC, status, paramp -> dscr_per_alloc);
  470. }
  471. size = sizeof (paramp -> tcp_dscr_timeout);
  472. status = RegQueryValueEx (key, CVY_NAME_TCP_TIMEOUT, 0L, & type,
  473. (LPBYTE) & paramp -> tcp_dscr_timeout, & size);
  474. if (status != ERROR_SUCCESS)
  475. {
  476. paramp -> tcp_dscr_timeout = CVY_DEF_TCP_TIMEOUT;
  477. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using %d", CVY_NAME_TCP_TIMEOUT, status, paramp -> tcp_dscr_timeout);
  478. }
  479. size = sizeof (paramp -> ipsec_dscr_timeout);
  480. status = RegQueryValueEx (key, CVY_NAME_IPSEC_TIMEOUT, 0L, & type,
  481. (LPBYTE) & paramp -> ipsec_dscr_timeout, & size);
  482. if (status != ERROR_SUCCESS)
  483. {
  484. paramp -> ipsec_dscr_timeout = CVY_DEF_IPSEC_TIMEOUT;
  485. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using %d", CVY_NAME_IPSEC_TIMEOUT, status, paramp -> ipsec_dscr_timeout);
  486. }
  487. size = sizeof (paramp -> filter_icmp);
  488. status = RegQueryValueEx (key, CVY_NAME_FILTER_ICMP, 0L, & type,
  489. (LPBYTE) & paramp -> filter_icmp, & size);
  490. if (status != ERROR_SUCCESS)
  491. {
  492. paramp -> filter_icmp = CVY_DEF_FILTER_ICMP;
  493. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using %d", CVY_NAME_FILTER_ICMP, status, paramp -> filter_icmp);
  494. }
  495. size = sizeof (paramp -> max_dscr_allocs);
  496. status = RegQueryValueEx (key, CVY_NAME_MAX_DSCR_ALLOCS, 0L, & type,
  497. (LPBYTE) & paramp -> max_dscr_allocs, & size);
  498. if (status != ERROR_SUCCESS)
  499. {
  500. paramp -> max_dscr_allocs = CVY_DEF_MAX_DSCR_ALLOCS;
  501. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using %d", CVY_NAME_MAX_DSCR_ALLOCS, status, paramp -> max_dscr_allocs);
  502. }
  503. size = sizeof (paramp -> i_scale_client);
  504. status = RegQueryValueEx (key, CVY_NAME_SCALE_CLIENT, 0L, & type,
  505. (LPBYTE) & paramp -> i_scale_client, & size);
  506. if (status != ERROR_SUCCESS)
  507. {
  508. paramp -> i_scale_client = CVY_DEF_SCALE_CLIENT;
  509. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using %d", CVY_NAME_SCALE_CLIENT, status, paramp -> i_scale_client);
  510. }
  511. size = sizeof (paramp -> i_cleanup_delay);
  512. status = RegQueryValueEx (key, CVY_NAME_CLEANUP_DELAY, 0L, & type,
  513. (LPBYTE) & paramp -> i_cleanup_delay, & size);
  514. if (status != ERROR_SUCCESS)
  515. {
  516. paramp -> i_cleanup_delay = CVY_DEF_CLEANUP_DELAY;
  517. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using %d", CVY_NAME_CLEANUP_DELAY, status, paramp -> i_cleanup_delay);
  518. }
  519. /* V1.1.1 */
  520. size = sizeof (paramp -> i_nbt_support);
  521. status = RegQueryValueEx (key, CVY_NAME_NBT_SUPPORT, 0L, & type,
  522. (LPBYTE) & paramp -> i_nbt_support, & size);
  523. if (status != ERROR_SUCCESS)
  524. {
  525. paramp -> i_nbt_support = CVY_DEF_NBT_SUPPORT;
  526. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using %d", CVY_NAME_NBT_SUPPORT, status, paramp -> i_nbt_support);
  527. }
  528. /* V1.3b */
  529. size = sizeof (paramp -> mcast_support);
  530. status = RegQueryValueEx (key, CVY_NAME_MCAST_SUPPORT, 0L, & type,
  531. (LPBYTE) & paramp -> mcast_support, & size);
  532. if (status != ERROR_SUCCESS)
  533. {
  534. paramp -> mcast_support = CVY_DEF_MCAST_SUPPORT;
  535. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using %d", CVY_NAME_MCAST_SUPPORT, status, paramp -> mcast_support);
  536. }
  537. size = sizeof (paramp -> i_mcast_spoof);
  538. status = RegQueryValueEx (key, CVY_NAME_MCAST_SPOOF, 0L, & type,
  539. (LPBYTE) & paramp -> i_mcast_spoof, & size);
  540. if (status != ERROR_SUCCESS)
  541. {
  542. paramp -> i_mcast_spoof = CVY_DEF_MCAST_SPOOF;
  543. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using %d", CVY_NAME_MCAST_SPOOF, status, paramp -> i_mcast_spoof);
  544. }
  545. size = sizeof (paramp -> mask_src_mac);
  546. status = RegQueryValueEx (key, CVY_NAME_MASK_SRC_MAC, 0L, & type,
  547. (LPBYTE) & paramp -> mask_src_mac, & size);
  548. if (status != ERROR_SUCCESS)
  549. {
  550. paramp -> mask_src_mac = CVY_DEF_MASK_SRC_MAC;
  551. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using %d", CVY_NAME_MASK_SRC_MAC, status, paramp -> mask_src_mac);
  552. }
  553. size = sizeof (paramp -> i_netmon_alive);
  554. status = RegQueryValueEx (key, CVY_NAME_NETMON_ALIVE, 0L, & type,
  555. (LPBYTE) & paramp -> i_netmon_alive, & size);
  556. if (status != ERROR_SUCCESS)
  557. {
  558. paramp -> i_netmon_alive = CVY_DEF_NETMON_ALIVE;
  559. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using %d", CVY_NAME_NETMON_ALIVE, status, paramp -> i_netmon_alive);
  560. }
  561. size = sizeof (paramp -> i_effective_version);
  562. status = RegQueryValueEx (key, CVY_NAME_EFFECTIVE_VERSION, 0L, & type,
  563. (LPBYTE) & paramp -> i_effective_version, & size);
  564. if (status != ERROR_SUCCESS)
  565. {
  566. paramp -> i_effective_version = CVY_NT40_VERSION_FULL;
  567. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using %d", CVY_NAME_EFFECTIVE_VERSION, status, paramp -> i_effective_version);
  568. }
  569. size = sizeof (paramp -> i_ip_chg_delay);
  570. status = RegQueryValueEx (key, CVY_NAME_IP_CHG_DELAY, 0L, & type,
  571. (LPBYTE) & paramp -> i_ip_chg_delay, & size);
  572. if (status != ERROR_SUCCESS)
  573. {
  574. paramp -> i_ip_chg_delay = CVY_DEF_IP_CHG_DELAY;
  575. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using %d", CVY_NAME_IP_CHG_DELAY, status, paramp -> i_ip_chg_delay);
  576. }
  577. size = sizeof (paramp -> i_convert_mac);
  578. status = RegQueryValueEx (key, CVY_NAME_CONVERT_MAC, 0L, & type,
  579. (LPBYTE) & paramp -> i_convert_mac, & size);
  580. if (status != ERROR_SUCCESS)
  581. {
  582. paramp -> i_convert_mac = CVY_DEF_CONVERT_MAC;
  583. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using %d", CVY_NAME_CONVERT_MAC, status, paramp -> i_convert_mac);
  584. }
  585. size = sizeof (paramp -> i_num_rules);
  586. status = RegQueryValueEx (key, CVY_NAME_NUM_RULES, 0L, & type,
  587. (LPBYTE) & paramp -> i_num_rules, & size);
  588. if (status != ERROR_SUCCESS)
  589. {
  590. paramp -> i_num_rules = 0;
  591. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using %d", CVY_NAME_NUM_RULES, status, paramp -> i_num_rules);
  592. }
  593. WLBS_OLD_PORT_RULE old_port_rules [WLBS_MAX_RULES];
  594. HKEY subkey;
  595. //
  596. // If it an upgrade from Win2k or if unable to open reg key in new location/format, read the binary formatted port
  597. // rules from old location. Otherwise, read from the new location.
  598. //
  599. status = ERROR_SUCCESS;
  600. if (fUpgradeFromWin2k
  601. || ((status = RegOpenKeyEx (key, CVY_NAME_PORT_RULES, 0L, KEY_QUERY_VALUE, & subkey)) != ERROR_SUCCESS))
  602. {
  603. // Did we enter the block due to failure of RegOpenKeyEx ?
  604. if (status != ERROR_SUCCESS)
  605. {
  606. TRACE_CRIT("%!FUNC! registry open for %ls failed with %d. Not an upgrade from Win2k, Assuming upgrade from pre-check-in whistler builds and continuing", CVY_NAME_PORT_RULES, status);
  607. }
  608. TRACE_INFO("%!FUNC! port rules are in binary form");
  609. if (pfPortRulesInBinaryForm)
  610. *pfPortRulesInBinaryForm = true;
  611. size = sizeof (old_port_rules);
  612. status = RegQueryValueEx (key, CVY_NAME_OLD_PORT_RULES, 0L, & type,
  613. (LPBYTE) old_port_rules, & size);
  614. if (status != ERROR_SUCCESS ||
  615. size % sizeof (WLBS_OLD_PORT_RULE) != 0 ||
  616. paramp -> i_num_rules != size / sizeof (WLBS_OLD_PORT_RULE))
  617. {
  618. ZeroMemory(paramp -> i_port_rules, sizeof(paramp -> i_port_rules));
  619. paramp -> i_num_rules = 0;
  620. TRACE_CRIT("%!FUNC! registry read for %ls failed. Skipping all rules", CVY_NAME_OLD_PORT_RULES);
  621. }
  622. else // Convert the port rules to new format
  623. {
  624. if (paramp -> i_parms_ver > 3)
  625. {
  626. TransformOldPortRulesToNew(old_port_rules, paramp -> i_port_rules, paramp -> i_num_rules);
  627. TRACE_INFO("%!FUNC! transforming binary port rules to current format");
  628. }
  629. else
  630. {
  631. TRACE_INFO("%!FUNC! no op on port rules because version is <= 3");
  632. }
  633. }
  634. }
  635. else // Port Rules in Textual Format
  636. {
  637. TRACE_INFO("%!FUNC! port rules are in textual form");
  638. DWORD idx = 1, num_rules = paramp -> i_num_rules, correct_rules = 0;
  639. WLBS_PORT_RULE *port_rule;
  640. if (pfPortRulesInBinaryForm)
  641. *pfPortRulesInBinaryForm = false;
  642. port_rule = paramp -> i_port_rules;
  643. while(idx <= num_rules)
  644. {
  645. HKEY rule_key;
  646. wchar_t idx_str[8];
  647. // Open the per port-rule key "1", "2", "3", ...etc
  648. if ((status = RegOpenKeyEx (subkey, _itow(idx, idx_str, 10), 0L, KEY_QUERY_VALUE, & rule_key)) != ERROR_SUCCESS)
  649. {
  650. idx++;
  651. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Skipping rule", idx_str, status);
  652. continue;
  653. }
  654. size = sizeof (port_rule -> virtual_ip_addr);
  655. status = RegQueryValueEx (rule_key, CVY_NAME_VIP, 0L, & type, (LPBYTE) &port_rule->virtual_ip_addr, & size);
  656. if (status != ERROR_SUCCESS)
  657. {
  658. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Skipping rule", CVY_NAME_VIP, status);
  659. status = RegCloseKey (rule_key);
  660. if (status != ERROR_SUCCESS)
  661. {
  662. TRACE_CRIT("%!FUNC! close registry for port rule %ls failed with %d",_itow(idx, idx_str, 10), status);
  663. }
  664. idx++;
  665. continue;
  666. }
  667. size = sizeof (port_rule ->start_port );
  668. status = RegQueryValueEx (rule_key, CVY_NAME_START_PORT, 0L, & type, (LPBYTE) &port_rule->start_port, & size);
  669. if (status != ERROR_SUCCESS)
  670. {
  671. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Skipping rule", CVY_NAME_START_PORT, status);
  672. status = RegCloseKey (rule_key);
  673. if (status != ERROR_SUCCESS)
  674. {
  675. TRACE_CRIT("%!FUNC! close registry for port rule %ls failed with %d",_itow(idx, idx_str, 10), status);
  676. }
  677. idx++;
  678. continue;
  679. }
  680. size = sizeof (port_rule ->end_port );
  681. status = RegQueryValueEx (rule_key, CVY_NAME_END_PORT, 0L, & type, (LPBYTE) &port_rule->end_port, & size);
  682. if (status != ERROR_SUCCESS)
  683. {
  684. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Skipping rule", CVY_NAME_END_PORT, status);
  685. status = RegCloseKey (rule_key);
  686. if (status != ERROR_SUCCESS)
  687. {
  688. TRACE_CRIT("%!FUNC! close registry for port rule %ls failed with %d",_itow(idx, idx_str, 10), status);
  689. }
  690. idx++;
  691. continue;
  692. }
  693. size = sizeof (port_rule ->code);
  694. status = RegQueryValueEx (rule_key, CVY_NAME_CODE, 0L, & type, (LPBYTE) &port_rule->code, & size);
  695. if (status != ERROR_SUCCESS)
  696. {
  697. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Skipping rule", CVY_NAME_CODE, status);
  698. status = RegCloseKey (rule_key);
  699. if (status != ERROR_SUCCESS)
  700. {
  701. TRACE_CRIT("%!FUNC! close registry for port rule %ls failed with %d",_itow(idx, idx_str, 10), status);
  702. }
  703. idx++;
  704. continue;
  705. }
  706. size = sizeof (port_rule->mode);
  707. status = RegQueryValueEx (rule_key, CVY_NAME_MODE, 0L, & type, (LPBYTE) &port_rule->mode, & size);
  708. if (status != ERROR_SUCCESS)
  709. {
  710. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Skipping rule", CVY_NAME_MODE, status);
  711. status = RegCloseKey (rule_key);
  712. if (status != ERROR_SUCCESS)
  713. {
  714. TRACE_CRIT("%!FUNC! close registry for port rule %ls failed with %d",_itow(idx, idx_str, 10), status);
  715. }
  716. idx++;
  717. continue;
  718. }
  719. size = sizeof (port_rule->protocol);
  720. status = RegQueryValueEx (rule_key, CVY_NAME_PROTOCOL, 0L, & type, (LPBYTE) &port_rule->protocol, & size);
  721. if (status != ERROR_SUCCESS)
  722. {
  723. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Skipping rule", CVY_NAME_PROTOCOL, status);
  724. status = RegCloseKey (rule_key);
  725. if (status != ERROR_SUCCESS)
  726. {
  727. TRACE_CRIT("%!FUNC! close registry for port rule %ls failed with %d",_itow(idx, idx_str, 10), status);
  728. }
  729. idx++;
  730. continue;
  731. }
  732. port_rule->valid = true;
  733. DWORD EqualLoad, Affinity;
  734. switch (port_rule->mode)
  735. {
  736. case CVY_MULTI :
  737. size = sizeof (EqualLoad);
  738. status = RegQueryValueEx (rule_key, CVY_NAME_EQUAL_LOAD, 0L, & type, (LPBYTE) &EqualLoad, & size);
  739. if (status != ERROR_SUCCESS)
  740. {
  741. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Skipping rule", CVY_NAME_EQUAL_LOAD, status);
  742. status = RegCloseKey (rule_key);
  743. if (status != ERROR_SUCCESS)
  744. {
  745. TRACE_CRIT("%!FUNC! close registry for port rule %ls failed with %d",_itow(idx, idx_str, 10), status);
  746. }
  747. idx++;
  748. continue;
  749. }
  750. else
  751. {
  752. port_rule->mode_data.multi.equal_load = (WORD) EqualLoad;
  753. TRACE_INFO("%!FUNC! registry read successful for %ls. Using equal load.", CVY_NAME_EQUAL_LOAD);
  754. }
  755. size = sizeof (Affinity);
  756. status = RegQueryValueEx (rule_key, CVY_NAME_AFFINITY, 0L, & type, (LPBYTE) &Affinity, & size);
  757. if (status != ERROR_SUCCESS)
  758. {
  759. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Skipping rule", CVY_NAME_AFFINITY, status);
  760. status = RegCloseKey (rule_key);
  761. if (status != ERROR_SUCCESS)
  762. {
  763. TRACE_CRIT("%!FUNC! close registry for port rule %ls failed with %d",_itow(idx, idx_str, 10), status);
  764. }
  765. idx++;
  766. continue;
  767. }
  768. else
  769. {
  770. port_rule->mode_data.multi.affinity = (WORD) Affinity;
  771. TRACE_INFO("%!FUNC! registry read successful for %ls. Using affinity %d", CVY_NAME_AFFINITY, port_rule->mode_data.multi.affinity);
  772. }
  773. size = sizeof (port_rule->mode_data.multi.load);
  774. status = RegQueryValueEx (rule_key, CVY_NAME_LOAD, 0L, & type, (LPBYTE) &(port_rule->mode_data.multi.load), & size);
  775. if (status != ERROR_SUCCESS)
  776. {
  777. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Skipping rule", CVY_NAME_LOAD, status);
  778. status = RegCloseKey (rule_key);
  779. if (status != ERROR_SUCCESS)
  780. {
  781. TRACE_CRIT("%!FUNC! close registry for port rule %ls failed with %d",_itow(idx, idx_str, 10), status);
  782. }
  783. idx++;
  784. continue;
  785. }
  786. break;
  787. case CVY_SINGLE :
  788. size = sizeof (port_rule->mode_data.single.priority);
  789. status = RegQueryValueEx (rule_key, CVY_NAME_PRIORITY, 0L, & type, (LPBYTE) &(port_rule->mode_data.single.priority), & size);
  790. if (status != ERROR_SUCCESS)
  791. {
  792. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Skipping rule", CVY_NAME_PRIORITY, status);
  793. status = RegCloseKey (rule_key);
  794. if (status != ERROR_SUCCESS)
  795. {
  796. TRACE_CRIT("%!FUNC! close registry for port rule %ls failed with %d",_itow(idx, idx_str, 10), status);
  797. }
  798. idx++;
  799. continue;
  800. }
  801. break;
  802. default:
  803. break;
  804. }
  805. // Close the per port rule key, ie. "1", "2", ...etc
  806. status = RegCloseKey (rule_key);
  807. if (status != ERROR_SUCCESS)
  808. {
  809. TRACE_CRIT("%!FUNC! close registry for port rule %ls failed with %d",_itow(idx, idx_str, 10), status);
  810. }
  811. port_rule++;
  812. idx++;
  813. correct_rules++;
  814. }
  815. // Discard those rules on which we encountered some error
  816. if (paramp->i_num_rules != correct_rules)
  817. {
  818. paramp -> i_num_rules = correct_rules;
  819. TRACE_INFO("%!FUNC! discarding rules for which errors were encountered");
  820. }
  821. // Close the "Port Rules" key
  822. status = RegCloseKey (subkey);
  823. if (status != ERROR_SUCCESS)
  824. {
  825. TRACE_CRIT("%!FUNC! close registry for %ls failed with %d", CVY_NAME_PORT_RULES, status);
  826. }
  827. }
  828. size = sizeof (paramp -> i_license_key);
  829. status = RegQueryValueEx (key, CVY_NAME_LICENSE_KEY, 0L, & type,
  830. (LPBYTE) paramp -> i_license_key, & size);
  831. if (status != ERROR_SUCCESS)
  832. {
  833. hresult = StringCbCopy (paramp -> i_license_key, sizeof(paramp -> i_license_key), CVY_DEF_LICENSE_KEY);
  834. if (FAILED(hresult))
  835. {
  836. TRACE_CRIT("%!FUNC! StringCbCopy failed, Error code : 0x%x", HRESULT_CODE(hresult));
  837. }
  838. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using %ls", CVY_NAME_LICENSE_KEY, status, CVY_DEF_LICENSE_KEY);
  839. }
  840. size = sizeof (paramp -> i_rmt_password);
  841. status = RegQueryValueEx (key, CVY_NAME_RMT_PASSWORD, 0L, & type,
  842. (LPBYTE) & paramp -> i_rmt_password, & size);
  843. if (status != ERROR_SUCCESS)
  844. {
  845. paramp -> i_rmt_password = CVY_DEF_RMT_PASSWORD;
  846. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using default rmt password", CVY_NAME_RMT_PASSWORD, status);
  847. }
  848. size = sizeof (paramp -> i_rct_password);
  849. status = RegQueryValueEx (key, CVY_NAME_RCT_PASSWORD, 0L, & type,
  850. (LPBYTE) & paramp -> i_rct_password, & size);
  851. if (status != ERROR_SUCCESS)
  852. {
  853. paramp -> i_rct_password = CVY_DEF_RCT_PASSWORD;
  854. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using default rct password", CVY_NAME_RCT_PASSWORD, status);
  855. }
  856. size = sizeof (paramp -> rct_port);
  857. status = RegQueryValueEx (key, CVY_NAME_RCT_PORT, 0L, & type,
  858. (LPBYTE) & paramp -> rct_port, & size);
  859. if (status != ERROR_SUCCESS)
  860. {
  861. paramp -> rct_port = CVY_DEF_RCT_PORT;
  862. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using %d", CVY_NAME_RCT_PORT, status, paramp -> rct_port);
  863. }
  864. size = sizeof (paramp -> rct_enabled);
  865. status = RegQueryValueEx (key, CVY_NAME_RCT_ENABLED, 0L, & type,
  866. (LPBYTE) & paramp -> rct_enabled, & size);
  867. if (status != ERROR_SUCCESS)
  868. {
  869. paramp -> rct_enabled = CVY_DEF_RCT_ENABLED;
  870. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using %d", CVY_NAME_RCT_ENABLED, status, paramp -> rct_enabled);
  871. }
  872. size = sizeof (paramp -> identity_period);
  873. status = RegQueryValueEx (key, CVY_NAME_ID_HB_PERIOD, 0L, & type,
  874. (LPBYTE) & paramp -> identity_period, & size);
  875. if (status != ERROR_SUCCESS)
  876. {
  877. paramp -> identity_period = CVY_DEF_ID_HB_PERIOD;
  878. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using %d", CVY_NAME_ID_HB_PERIOD, status, paramp -> identity_period);
  879. }
  880. size = sizeof (paramp -> identity_enabled);
  881. status = RegQueryValueEx (key, CVY_NAME_ID_HB_ENABLED, 0L, & type,
  882. (LPBYTE) & paramp -> identity_enabled, & size);
  883. if (status != ERROR_SUCCESS)
  884. {
  885. paramp -> identity_enabled = CVY_DEF_ID_HB_ENABLED;
  886. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using %d", CVY_NAME_ID_HB_ENABLED, status, paramp -> identity_enabled);
  887. }
  888. //
  889. // IGMP support registry entries
  890. //
  891. size = sizeof (paramp->fIGMPSupport);
  892. status = RegQueryValueEx (key, CVY_NAME_IGMP_SUPPORT, 0L, NULL,
  893. (LPBYTE) & paramp->fIGMPSupport, &size);
  894. if (status != ERROR_SUCCESS)
  895. {
  896. paramp -> fIGMPSupport = CVY_DEF_IGMP_SUPPORT;
  897. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. igmp support will be disabled", CVY_NAME_IGMP_SUPPORT, status);
  898. }
  899. size = sizeof (paramp->szMCastIpAddress);
  900. status = RegQueryValueEx (key, CVY_NAME_MCAST_IP_ADDR, 0L, NULL,
  901. (LPBYTE) & paramp->szMCastIpAddress, &size);
  902. if (status != ERROR_SUCCESS)
  903. {
  904. hresult = StringCbCopy(paramp -> szMCastIpAddress, sizeof(paramp -> szMCastIpAddress), CVY_DEF_MCAST_IP_ADDR);
  905. if (SUCCEEDED(hresult))
  906. {
  907. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using %ls", CVY_NAME_MCAST_IP_ADDR, status, paramp -> szMCastIpAddress);
  908. }
  909. else
  910. {
  911. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Initializing with default also failed, Error code : 0x%x", CVY_NAME_MCAST_IP_ADDR, status, HRESULT_CODE(hresult));
  912. }
  913. }
  914. size = sizeof (paramp->fIpToMCastIp);
  915. status = RegQueryValueEx (key, CVY_NAME_IP_TO_MCASTIP, 0L, NULL,
  916. (LPBYTE) & paramp->fIpToMCastIp, &size);
  917. if (status != ERROR_SUCCESS)
  918. {
  919. paramp -> fIpToMCastIp = CVY_DEF_IP_TO_MCASTIP;
  920. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. ip to multicast flag will be set to true", CVY_NAME_IP_TO_MCASTIP, status);
  921. }
  922. /* Attempt to open the BDA teaming settings. They may not be there,
  923. so if they aren't, move on; otherwise, extract the settings. */
  924. if ((bda_key = RegOpenWlbsBDASettings(AdapterGuid, true))) {
  925. GUID TeamGuid;
  926. HRESULT hr;
  927. /* If the key exists, we are part of a team. */
  928. paramp->bda_teaming.active = TRUE;
  929. /* Find out if we are the master of this team. */
  930. size = sizeof (paramp->bda_teaming.master);
  931. status = RegQueryValueEx (bda_key, CVY_NAME_BDA_MASTER, 0L, NULL,
  932. (LPBYTE)&paramp->bda_teaming.master, &size);
  933. /* If we can't get that information, default to a slave. */
  934. if (status != ERROR_SUCCESS)
  935. {
  936. paramp->bda_teaming.master = FALSE;
  937. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. teaming master will be set to false", CVY_NAME_BDA_MASTER, status);
  938. }
  939. /* Find out if we are reverse hashing or not. */
  940. size = sizeof (paramp->bda_teaming.reverse_hash);
  941. status = RegQueryValueEx (bda_key, CVY_NAME_BDA_REVERSE_HASH, 0L, NULL,
  942. (LPBYTE)&paramp->bda_teaming.reverse_hash, &size);
  943. /* If that fails, then assume normal hashing. */
  944. if (status != ERROR_SUCCESS)
  945. {
  946. paramp->bda_teaming.reverse_hash = FALSE;
  947. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. teaming master will be set to false", CVY_NAME_BDA_REVERSE_HASH, status);
  948. }
  949. /* Get our team ID - this should be a GUID, be we don't enforce that. */
  950. size = sizeof (paramp->bda_teaming.team_id);
  951. status = RegQueryValueEx (bda_key, CVY_NAME_BDA_TEAM_ID, 0L, NULL,
  952. (LPBYTE)&paramp->bda_teaming.team_id, &size);
  953. /* The team is absolutely required - if we can't get it, then don't join the team. */
  954. if (status != ERROR_SUCCESS)
  955. {
  956. paramp->bda_teaming.active = CVY_DEF_BDA_ACTIVE;
  957. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d. Using %d", CVY_NAME_BDA_TEAM_ID, status, paramp->bda_teaming.active);
  958. }
  959. /* Attempt to convert the string to a GUID and check for errors. */
  960. hr = CLSIDFromString(paramp->bda_teaming.team_id, &TeamGuid);
  961. /* If the conversion fails, bail out - the team ID must not have been a GUID. */
  962. if (hr != NOERROR) {
  963. paramp->bda_teaming.active = CVY_DEF_BDA_ACTIVE;
  964. TRACE_CRIT("%!FUNC! Invalid BDA Team ID: %ls. Setting bda teaming active flag to %d", paramp->bda_teaming.team_id, paramp->bda_teaming.active);
  965. }
  966. status = RegCloseKey(bda_key);
  967. if (status != ERROR_SUCCESS)
  968. {
  969. TRACE_CRIT("%!FUNC! close bda registry key failed with %d", status);
  970. }
  971. }
  972. /* decode port rules prior to version 3 */
  973. if (paramp -> i_parms_ver <= 3)
  974. {
  975. TRACE_INFO("%!FUNC! port rule is version %d", paramp -> i_parms_ver);
  976. paramp -> i_parms_ver = CVY_PARAMS_VERSION;
  977. /* decode the port rules */
  978. if (! License_data_decode ((PCHAR) old_port_rules, paramp -> i_num_rules * sizeof (WLBS_OLD_PORT_RULE)))
  979. {
  980. ZeroMemory(paramp -> i_port_rules, sizeof(paramp -> i_port_rules));
  981. paramp -> i_num_rules = 0;
  982. TRACE_CRIT("%!FUNC! port rule decode failed. Skipping rules");
  983. }
  984. else
  985. {
  986. TransformOldPortRulesToNew(old_port_rules, paramp -> i_port_rules, paramp -> i_num_rules);
  987. TRACE_INFO("%!FUNC! port rules transformed to current format");
  988. }
  989. }
  990. /* upgrade port rules from params V1 to params V2 */
  991. if (paramp -> i_parms_ver == 1)
  992. {
  993. TRACE_INFO("%!FUNC! upgrading version 1 port rule");
  994. paramp -> i_parms_ver = CVY_PARAMS_VERSION;
  995. /* keep multicast off by default for old users */
  996. paramp -> mcast_support = FALSE;
  997. for (i = 0; i < paramp -> i_num_rules; i ++)
  998. {
  999. rp = paramp -> i_port_rules + i;
  1000. code = CVY_RULE_CODE_GET (rp);
  1001. CVY_RULE_CODE_SET (rp);
  1002. if (code != CVY_RULE_CODE_GET (rp))
  1003. {
  1004. rp -> code = code;
  1005. continue;
  1006. }
  1007. if (! rp -> valid)
  1008. {
  1009. TRACE_INFO("%!FUNC! port rule is invalid. Skip it.");
  1010. continue;
  1011. }
  1012. /* set affinity according to current ScaleSingleClient setting */
  1013. if (rp -> mode == CVY_MULTI)
  1014. rp -> mode_data . multi . affinity = CVY_AFFINITY_SINGLE - (USHORT)paramp -> i_scale_client;
  1015. CVY_RULE_CODE_SET (rp);
  1016. }
  1017. }
  1018. /* upgrade max number of descriptor allocs */
  1019. if (paramp -> i_parms_ver == 2)
  1020. {
  1021. TRACE_INFO("%!FUNC! upgrading properties for version 2");
  1022. paramp -> i_parms_ver = CVY_PARAMS_VERSION;
  1023. paramp -> max_dscr_allocs = CVY_DEF_MAX_DSCR_ALLOCS;
  1024. paramp -> dscr_per_alloc = CVY_DEF_DSCR_PER_ALLOC;
  1025. }
  1026. status = RegCloseKey (key);
  1027. if (status != ERROR_SUCCESS)
  1028. {
  1029. TRACE_CRIT("%!FUNC! close registry key failed with %d", status);
  1030. }
  1031. paramp -> i_max_hosts = CVY_MAX_HOSTS;
  1032. paramp -> i_max_rules = CVY_MAX_USABLE_RULES;
  1033. // paramp -> i_ft_rules_enabled = TRUE;
  1034. // paramp -> version = 0;
  1035. // CLEAN_64BIT CVY_CHECK_MIN (paramp -> i_num_rules, CVY_MIN_NUM_RULES);
  1036. CVY_CHECK_MAX (paramp -> i_num_rules, CVY_MAX_NUM_RULES);
  1037. CVY_CHECK_MIN (paramp -> host_priority, CVY_MIN_HOST_PRIORITY);
  1038. CVY_CHECK_MAX (paramp -> host_priority, CVY_MAX_HOST_PRIORITY);
  1039. TRACE_VERB("<-%!FUNC! return true");
  1040. return TRUE;
  1041. }
  1042. //+----------------------------------------------------------------------------
  1043. //
  1044. // Function: WlbsValidateParams
  1045. //
  1046. // Description: Validates the cluster parameters. Also munges some fields
  1047. // such as IP addresses to make them canonocal.
  1048. //
  1049. // Arguments: PWLBS_REG_PARAMS paramp -
  1050. //
  1051. // Returns: bool - TRUE if params are valid, false otherwise
  1052. //
  1053. // History: josephj Created 4/25/01 based on code from ParamWriteReg.
  1054. // karthicn Edited 8/31/01 renamed from ParamValidate to WlbsValidateParams
  1055. //
  1056. //+----------------------------------------------------------------------------
  1057. BOOL WINAPI WlbsValidateParams(const PWLBS_REG_PARAMS paramp)
  1058. {
  1059. TRACE_VERB("->%!FUNC!");
  1060. bool fRet = FALSE;
  1061. DWORD idx;
  1062. IN_ADDR dwIPAddr;
  1063. CHAR * szIPAddr;
  1064. DWORD num_rules;
  1065. WLBS_PORT_RULE *port_rule;
  1066. /* verify and if necessary reset the parameters */
  1067. //
  1068. // We don't validate the lower bound for unsigned words when the lower bound is 0. Otherwise we
  1069. // get a compiler warning, promoted to an error, because such a test can't fail
  1070. //
  1071. // Ignore lower bound checking
  1072. //
  1073. CVY_CHECK_MAX (paramp -> i_scale_client, CVY_MAX_SCALE_CLIENT);
  1074. CVY_CHECK_MAX (paramp -> i_nbt_support, CVY_MAX_NBT_SUPPORT);
  1075. CVY_CHECK_MAX (paramp -> mcast_support, CVY_MAX_MCAST_SUPPORT);
  1076. CVY_CHECK_MAX (paramp -> i_mcast_spoof, CVY_MAX_MCAST_SPOOF);
  1077. CVY_CHECK_MAX (paramp -> mask_src_mac, CVY_MAX_MASK_SRC_MAC);
  1078. CVY_CHECK_MAX (paramp -> i_netmon_alive, CVY_MAX_NETMON_ALIVE);
  1079. CVY_CHECK_MAX (paramp -> i_convert_mac, CVY_MAX_CONVERT_MAC);
  1080. CVY_CHECK_MAX (paramp -> rct_port, CVY_MAX_RCT_PORT);
  1081. CVY_CHECK_MAX (paramp -> rct_enabled, CVY_MAX_RCT_ENABLED);
  1082. CVY_CHECK_MAX (paramp -> i_cleanup_delay, CVY_MAX_CLEANUP_DELAY);
  1083. CVY_CHECK_MAX (paramp -> i_ip_chg_delay, CVY_MAX_IP_CHG_DELAY);
  1084. CVY_CHECK_MAX (paramp -> i_num_rules, CVY_MAX_NUM_RULES);
  1085. CVY_CHECK_MAX (paramp -> cluster_mode, CVY_MAX_CLUSTER_MODE);
  1086. CVY_CHECK_MAX (paramp -> tcp_dscr_timeout, CVY_MAX_TCP_TIMEOUT);
  1087. CVY_CHECK_MAX (paramp -> ipsec_dscr_timeout, CVY_MAX_IPSEC_TIMEOUT);
  1088. CVY_CHECK_MAX (paramp -> filter_icmp, CVY_MAX_FILTER_ICMP);
  1089. CVY_CHECK_MAX (paramp -> identity_enabled, CVY_MAX_ID_HB_ENABLED);
  1090. //
  1091. // End Ignore lower bound checking
  1092. //
  1093. //
  1094. // CVY_NAME_VERSION is not validated since its value is used and manipulated before we get here
  1095. // CVY_NAME_LICENSE_KEY is not validated since it can take any value.
  1096. // RMT_PASSWORD is not validated since it can take any storable value
  1097. // RCT_PASSWORD is not validated since it can take any storable value
  1098. // CVY_NAME_IGMP_SUPPORT is not validated because it is of BOOL type and can thus take any value
  1099. // CVY_NAME_IP_TO_MCASTIP is not validated because it is of BOOL type and can thus take any value
  1100. //
  1101. CVY_CHECK_MIN (paramp -> alive_period, CVY_MIN_ALIVE_PERIOD);
  1102. CVY_CHECK_MAX (paramp -> alive_period, CVY_MAX_ALIVE_PERIOD);
  1103. CVY_CHECK_MIN (paramp -> alive_tolerance, CVY_MIN_ALIVE_TOLER);
  1104. CVY_CHECK_MAX (paramp -> alive_tolerance, CVY_MAX_ALIVE_TOLER);
  1105. CVY_CHECK_MIN (paramp -> num_actions, CVY_MIN_NUM_ACTIONS);
  1106. CVY_CHECK_MAX (paramp -> num_actions, CVY_MAX_NUM_ACTIONS);
  1107. CVY_CHECK_MIN (paramp -> num_packets, CVY_MIN_NUM_PACKETS);
  1108. CVY_CHECK_MAX (paramp -> num_packets, CVY_MAX_NUM_PACKETS);
  1109. CVY_CHECK_MIN (paramp -> dscr_per_alloc, CVY_MIN_DSCR_PER_ALLOC);
  1110. CVY_CHECK_MAX (paramp -> dscr_per_alloc, CVY_MAX_DSCR_PER_ALLOC);
  1111. CVY_CHECK_MIN (paramp -> max_dscr_allocs, CVY_MIN_MAX_DSCR_ALLOCS);
  1112. CVY_CHECK_MAX (paramp -> max_dscr_allocs, CVY_MAX_MAX_DSCR_ALLOCS);
  1113. CVY_CHECK_MIN (paramp -> num_send_msgs, (paramp -> i_max_hosts + 1) * 2);
  1114. CVY_CHECK_MAX (paramp -> num_send_msgs, (paramp -> i_max_hosts + 1) * 10);
  1115. CVY_CHECK_MIN (paramp -> host_priority, CVY_MIN_HOST_PRIORITY);
  1116. CVY_CHECK_MAX (paramp -> host_priority, CVY_MAX_HOST_PRIORITY);
  1117. CVY_CHECK_MIN (paramp -> identity_period, CVY_MIN_ID_HB_PERIOD);
  1118. CVY_CHECK_MAX (paramp -> identity_period, CVY_MAX_ID_HB_PERIOD);
  1119. /* If the cluster IP address is not 0.0.0.0, then make sure the IP address is valid. */
  1120. if (lstrcmpi(paramp->cl_ip_addr, CVY_DEF_CL_IP_ADDR)) {
  1121. /* Check the validity of the IP address. */
  1122. if (!(dwIPAddr.S_un.S_addr = IpAddressFromAbcdWsz(paramp->cl_ip_addr)))
  1123. goto error;
  1124. /* Convert the DWORD back to a string. We do this because 11.11.3 is a valid IP
  1125. address the inet_addr converts to 11.11.0.3 as a DWORD. Therefore, to keep
  1126. the IP address string (which is used by other parts of NLB, such as the UI)
  1127. consistent, we convert back to a string. */
  1128. if (!(szIPAddr = inet_ntoa(dwIPAddr)))
  1129. goto error;
  1130. /* Convert the ASCII string to unicode. */
  1131. if (!MultiByteToWideChar(CP_ACP, 0, szIPAddr, -1, paramp->cl_ip_addr, WLBS_MAX_CL_IP_ADDR + 1))
  1132. goto error;
  1133. }
  1134. /* If the cluster netmask is not 0.0.0.0, then make sure the netmask is valid. */
  1135. if (lstrcmpi(paramp->cl_net_mask, CVY_DEF_CL_NET_MASK)) {
  1136. /* Check the validity of the IP address. */
  1137. if (!(dwIPAddr.S_un.S_addr = IpAddressFromAbcdWsz(paramp->cl_net_mask)))
  1138. goto error;
  1139. /* Convert the DWORD back to a string. We do this because 11.11.3 is a valid IP
  1140. address the inet_addr converts to 11.11.0.3 as a DWORD. Therefore, to keep
  1141. the IP address string (which is used by other parts of NLB, such as the UI)
  1142. consistent, we convert back to a string. */
  1143. if (!(szIPAddr = inet_ntoa(dwIPAddr)))
  1144. goto error;
  1145. /* Convert the ASCII string to unicode. */
  1146. if (!MultiByteToWideChar(CP_ACP, 0, szIPAddr, -1, paramp->cl_net_mask, WLBS_MAX_CL_NET_MASK + 1))
  1147. goto error;
  1148. }
  1149. /* If the dedicated IP address is not 0.0.0.0, then make sure the IP address is valid. */
  1150. if (lstrcmpi(paramp->ded_ip_addr, CVY_DEF_DED_IP_ADDR)) {
  1151. /* Check the validity of the IP address. */
  1152. if (!(dwIPAddr.S_un.S_addr = IpAddressFromAbcdWsz(paramp->ded_ip_addr)))
  1153. goto error;
  1154. /* Convert the DWORD back to a string. We do this because 11.11.3 is a valid IP
  1155. address the inet_addr converts to 11.11.0.3 as a DWORD. Therefore, to keep
  1156. the IP address string (which is used by other parts of NLB, such as the UI)
  1157. consistent, we convert back to a string. */
  1158. if (!(szIPAddr = inet_ntoa(dwIPAddr)))
  1159. goto error;
  1160. /* Convert the ASCII string to unicode. */
  1161. if (!MultiByteToWideChar(CP_ACP, 0, szIPAddr, -1, paramp->ded_ip_addr, WLBS_MAX_DED_IP_ADDR + 1))
  1162. goto error;
  1163. }
  1164. /* If the dedicated netmask is not 0.0.0.0, then make sure the netmask is valid. */
  1165. if (lstrcmpi(paramp->ded_net_mask, CVY_DEF_DED_NET_MASK)) {
  1166. /* Check the validity of the IP address. */
  1167. if (!(dwIPAddr.S_un.S_addr = IpAddressFromAbcdWsz(paramp->ded_net_mask)))
  1168. goto error;
  1169. /* Convert the DWORD back to a string. We do this because 11.11.3 is a valid IP
  1170. address the inet_addr converts to 11.11.0.3 as a DWORD. Therefore, to keep
  1171. the IP address string (which is used by other parts of NLB, such as the UI)
  1172. consistent, we convert back to a string. */
  1173. if (!(szIPAddr = inet_ntoa(dwIPAddr)))
  1174. goto error;
  1175. /* Convert the ASCII string to unicode. */
  1176. if (!MultiByteToWideChar(CP_ACP, 0, szIPAddr, -1, paramp->ded_net_mask, WLBS_MAX_DED_NET_MASK + 1))
  1177. goto error;
  1178. }
  1179. /* Verify that the port rule VIP is valid,
  1180. Also, convert the port rule VIPs that might be in the x.x.x or x.x or x form to x.x.x.x */
  1181. idx = 0;
  1182. num_rules = paramp -> i_num_rules;
  1183. while (idx < num_rules)
  1184. {
  1185. port_rule = &paramp->i_port_rules[idx];
  1186. /* Check if the port rule is valid and the vip is not "All Vip" */
  1187. if (port_rule->valid && lstrcmpi(port_rule->virtual_ip_addr, CVY_DEF_ALL_VIP))
  1188. {
  1189. /* Get IP Address into DWORD form */
  1190. if (!(dwIPAddr.S_un.S_addr = IpAddressFromAbcdWsz(port_rule->virtual_ip_addr)))
  1191. goto error;
  1192. /* Check for validity of IP Address */
  1193. if ((dwIPAddr.S_un.S_un_b.s_b1 < WLBS_IP_FIELD_ZERO_LOW)
  1194. || (dwIPAddr.S_un.S_un_b.s_b1 > WLBS_IP_FIELD_ZERO_HIGH)
  1195. || (dwIPAddr.S_un.S_un_b.s_b2 < WLBS_FIELD_LOW)
  1196. || (dwIPAddr.S_un.S_un_b.s_b2 > WLBS_FIELD_HIGH)
  1197. || (dwIPAddr.S_un.S_un_b.s_b3 < WLBS_FIELD_LOW)
  1198. || (dwIPAddr.S_un.S_un_b.s_b3 > WLBS_FIELD_HIGH)
  1199. || (dwIPAddr.S_un.S_un_b.s_b4 < WLBS_FIELD_LOW)
  1200. || (dwIPAddr.S_un.S_un_b.s_b4 > WLBS_FIELD_HIGH))
  1201. goto error;
  1202. /* Convert the DWORD back to a string. We do this because 11.11.3 is a valid IP
  1203. address the inet_addr converts to 11.11.0.3 as a DWORD. Therefore, to keep
  1204. the IP address string (which is used by other parts of NLB, such as the UI)
  1205. consistent, we convert back to a string. */
  1206. if (!(szIPAddr = inet_ntoa(dwIPAddr)))
  1207. goto error;
  1208. /* Convert the ASCII string to unicode. */
  1209. if (!MultiByteToWideChar(CP_ACP, 0, szIPAddr, -1, port_rule->virtual_ip_addr, WLBS_MAX_CL_IP_ADDR + 1))
  1210. goto error;
  1211. }
  1212. idx++;
  1213. }
  1214. /* If either the cluster IP address or the cluster netmask is not 0.0.0.0,
  1215. then make sure the they are a valid IP address/netmask pair. */
  1216. if (lstrcmpi(paramp->cl_ip_addr, CVY_DEF_CL_IP_ADDR) || lstrcmpi(paramp->cl_net_mask, CVY_DEF_CL_NET_MASK)) {
  1217. /* If they have specified a cluster IP address, but no netmask, then fill it in for them. */
  1218. if (!lstrcmpi(paramp->cl_net_mask, CVY_DEF_CL_NET_MASK))
  1219. {
  1220. ParamsGenerateSubnetMask(paramp->cl_ip_addr, paramp->cl_net_mask, ASIZECCH(paramp->cl_net_mask));
  1221. }
  1222. /* Check for valid cluster IP address/netmask pairs. */
  1223. if (!IsValidIPAddressSubnetMaskPair(paramp->cl_ip_addr, paramp->cl_net_mask))
  1224. goto error;
  1225. /* Check to make sure that the cluster netmask is contiguous. */
  1226. if (!IsContiguousSubnetMask(paramp->cl_net_mask))
  1227. goto error;
  1228. /* Check to make sure that the dedicated IP and cluster IP are not the same. */
  1229. if (!wcscmp(paramp->ded_ip_addr, paramp->cl_ip_addr))
  1230. goto error;
  1231. }
  1232. /* If either the dedicated IP address or the dedicated netmask is not 0.0.0.0,
  1233. then make sure the they are a valid IP address/netmask pair. */
  1234. if (lstrcmpi(paramp->ded_ip_addr, CVY_DEF_DED_IP_ADDR) || lstrcmpi(paramp->ded_net_mask, CVY_DEF_DED_NET_MASK)) {
  1235. /* If they have specified a cluster IP address, but no netmask, then fill it in for them. */
  1236. if (!lstrcmpi(paramp->ded_net_mask, CVY_DEF_DED_NET_MASK))
  1237. {
  1238. ParamsGenerateSubnetMask(paramp->ded_ip_addr, paramp->ded_net_mask, ASIZECCH(paramp->ded_net_mask));
  1239. }
  1240. /* Check for valid dedicated IP address/netmask pairs. */
  1241. if (!IsValidIPAddressSubnetMaskPair(paramp->ded_ip_addr, paramp->ded_net_mask))
  1242. goto error;
  1243. /* Check to make sure that the dedicated netmask is contiguous. */
  1244. if (!IsContiguousSubnetMask(paramp->ded_net_mask))
  1245. goto error;
  1246. }
  1247. /* Check the mac address if the convert_mac flag is not set */
  1248. if ( ! paramp -> i_convert_mac)
  1249. {
  1250. PWCHAR p1, p2;
  1251. WCHAR mac_addr [WLBS_MAX_NETWORK_ADDR + 1];
  1252. DWORD i, j;
  1253. BOOL flag = TRUE;
  1254. HRESULT hresult;
  1255. hresult = StringCbCopy (mac_addr, sizeof(mac_addr), paramp -> cl_mac_addr);
  1256. if (FAILED(hresult))
  1257. goto error;
  1258. p2 = p1 = mac_addr;
  1259. for (i = 0 ; i < 6 ; i++)
  1260. {
  1261. if (*p2 == _TEXT('\0'))
  1262. {
  1263. flag = FALSE;
  1264. break;
  1265. }
  1266. j = _tcstoul (p1, &p2, 16);
  1267. if ( j > 255)
  1268. {
  1269. flag = FALSE;
  1270. break;
  1271. }
  1272. if ( ! (*p2 == _TEXT('-') || *p2 == _TEXT(':') || *p2 == _TEXT('\0')) )
  1273. {
  1274. flag = FALSE;
  1275. break;
  1276. }
  1277. if (*p2 == _TEXT('\0') && i < 5)
  1278. {
  1279. flag = FALSE;
  1280. break;
  1281. }
  1282. p1 = p2 + 1;
  1283. p2 = p1;
  1284. }
  1285. if (!flag)
  1286. {
  1287. goto error;
  1288. }
  1289. }
  1290. if (paramp->fIGMPSupport && !paramp->mcast_support)
  1291. {
  1292. //
  1293. // IGMP can not be enabled in unicast mode
  1294. //
  1295. TRACE_CRIT("%!FUNC! IGMP can not be enabled in unicast mode");
  1296. goto error;
  1297. }
  1298. if (paramp->mcast_support && paramp->fIGMPSupport && !paramp->fIpToMCastIp)
  1299. {
  1300. //
  1301. // Verify that the multicast IP is a valid IP form. Ignore default value case since it isn't a valid IP.
  1302. //
  1303. if (lstrcmpi(paramp -> szMCastIpAddress, CVY_DEF_MCAST_IP_ADDR)) {
  1304. /* Check the validity of the IP address. */
  1305. if (!(dwIPAddr.S_un.S_addr = IpAddressFromAbcdWsz(paramp -> szMCastIpAddress)))
  1306. goto error;
  1307. /* Convert the DWORD back to a string. We do this because 11.11.3 is a valid IP
  1308. address the inet_addr converts to 11.11.0.3 as a DWORD. Therefore, to keep
  1309. the IP address string (which is used by other parts of NLB, such as the UI)
  1310. consistent, we convert back to a string. */
  1311. if (!(szIPAddr = inet_ntoa(dwIPAddr)))
  1312. goto error;
  1313. /* Convert the ASCII string to unicode. */
  1314. if (!MultiByteToWideChar(CP_ACP, 0, szIPAddr, -1, paramp -> szMCastIpAddress, WLBS_MAX_CL_IP_ADDR + 1))
  1315. goto error;
  1316. }
  1317. //
  1318. // Multicast mode with IGMP enabled, and user specified an multicast IP address,
  1319. // The multicast IP address should be in the range of (224-239).x.x.x
  1320. // but NOT (224-239).0.0.x or (224-239).128.0.x.
  1321. //
  1322. DWORD dwMCastIp = IpAddressFromAbcdWsz(paramp->szMCastIpAddress);
  1323. if ((dwMCastIp & 0xf0) != 0xe0 ||
  1324. (dwMCastIp & 0x00ffff00) == 0 ||
  1325. (dwMCastIp & 0x00ffff00) == 0x00008000)
  1326. {
  1327. TRACE_CRIT("%!FUNC! invalid szMCastIpAddress %ws", paramp->szMCastIpAddress);
  1328. goto error;
  1329. }
  1330. }
  1331. /* Generate the MAC address. */
  1332. ParamsGenerateMAC(paramp->cl_ip_addr, paramp->cl_mac_addr, ASIZECCH(paramp->cl_mac_addr), paramp->szMCastIpAddress, ASIZECCH(paramp->szMCastIpAddress), paramp->i_convert_mac,
  1333. paramp->mcast_support, paramp->fIGMPSupport, paramp->fIpToMCastIp);
  1334. //
  1335. // We only process bda information if bda teaming is active. We can ignore these properties if it isn't. Dependencies
  1336. // such as WriteRegParam will check this too to see if they should process the information.
  1337. //
  1338. if (paramp -> bda_teaming . active) {
  1339. GUID TeamGuid;
  1340. HRESULT hr;
  1341. //
  1342. // We don't validate the lower bound for unsigned words when the lower bound is 0. Otherwise we
  1343. // get a compiler warning, promoted to an error, because such a test can't fail
  1344. //
  1345. // Ignore lower bound checking
  1346. //
  1347. CVY_CHECK_MAX (paramp -> bda_teaming . master, 1);
  1348. CVY_CHECK_MAX (paramp -> bda_teaming . reverse_hash, 1);
  1349. //
  1350. // End Ignore lower bound checking
  1351. //
  1352. //
  1353. // A teaming ID must be a GUID. Validate that it is, but we don't care what value. This means we ignore
  1354. // the content of TeamGuid.
  1355. //
  1356. hr = CLSIDFromString(paramp -> bda_teaming . team_id, &TeamGuid);
  1357. // If the conversion fails, bail out - the team ID must not have been a GUID
  1358. if (hr != NOERROR) {
  1359. TRACE_CRIT("%!FUNC! invalid BDA Team ID: %ls", paramp->bda_teaming.team_id);
  1360. goto error;
  1361. }
  1362. }
  1363. fRet = TRUE;
  1364. goto end;
  1365. error:
  1366. fRet = FALSE;
  1367. goto end;
  1368. end:
  1369. TRACE_VERB("<-%!FUNC! return %d", fRet);
  1370. return fRet;
  1371. }
  1372. //+----------------------------------------------------------------------------
  1373. //
  1374. // Function: WlbsWriteAndCommitChanges
  1375. //
  1376. // Description: Write cluster settings to registry, Commits the changes to NLB driver
  1377. //
  1378. // Arguments: Adapter GUID, Handle to NLB driver, New registry parameters
  1379. //
  1380. // Returns: DWORD -
  1381. //
  1382. // History: KarthicN Created 8/28/01
  1383. //
  1384. //+----------------------------------------------------------------------------
  1385. DWORD WINAPI WlbsWriteAndCommitChanges(HANDLE NlbHdl,
  1386. const GUID * pAdapterGuid,
  1387. WLBS_REG_PARAMS* p_new_reg_params)
  1388. {
  1389. TRACE_VERB("->%!FUNC!");
  1390. DWORD Status;
  1391. WLBS_REG_PARAMS cur_reg_params;
  1392. bool reload_required;
  1393. bool notify_adapter_required;
  1394. // Read NLB registry paramters for passing it into ParamWriteConfig
  1395. if (ParamReadReg(*pAdapterGuid, &cur_reg_params) == false)
  1396. {
  1397. TRACE_VERB("<-%!FUNC! return %d", WLBS_REG_ERROR);
  1398. return WLBS_REG_ERROR;
  1399. }
  1400. reload_required = false;
  1401. notify_adapter_required = false;
  1402. // Write NLB registry parameters
  1403. Status = ParamWriteConfig(*pAdapterGuid,
  1404. p_new_reg_params,
  1405. &cur_reg_params,
  1406. &reload_required,
  1407. &notify_adapter_required);
  1408. if (Status != WLBS_OK)
  1409. {
  1410. TRACE_VERB("<-%!FUNC! return %d", Status);
  1411. return Status;
  1412. }
  1413. // If reload_required flag is set, commit changes
  1414. if (reload_required)
  1415. {
  1416. DWORD cl_addr, ded_addr;
  1417. Status = ParamCommitChanges(*pAdapterGuid,
  1418. NlbHdl,
  1419. cl_addr,
  1420. ded_addr,
  1421. &reload_required,
  1422. &notify_adapter_required);
  1423. if (Status != WLBS_OK)
  1424. {
  1425. TRACE_VERB("<-%!FUNC! return %d", Status);
  1426. return Status;
  1427. }
  1428. }
  1429. TRACE_VERB("<-%!FUNC! return %d", Status);
  1430. return Status;
  1431. }
  1432. //+----------------------------------------------------------------------------
  1433. //
  1434. // Function: ParamWriteConfig
  1435. //
  1436. // Description: Write cluster settings to registry
  1437. //
  1438. // Arguments: Adapter GUID, New registry parameters, Old registry parameters,
  1439. // Reload_required flag, Notify_adapter_required flag
  1440. //
  1441. // Returns: DWORD -
  1442. //
  1443. // History: KarthicN Created 8/28/01
  1444. // 12/2/01 ChrisDar Modified to change the adapter notification conditions.
  1445. // Was for mac change only; added for cluster IP change too.
  1446. //
  1447. //+----------------------------------------------------------------------------
  1448. DWORD ParamWriteConfig(const GUID& AdapterGuid,
  1449. WLBS_REG_PARAMS* new_reg_params,
  1450. WLBS_REG_PARAMS* old_reg_params,
  1451. bool * p_reload_required,
  1452. bool * p_notify_adapter_required)
  1453. {
  1454. TRACE_VERB("->%!FUNC!");
  1455. if (memcmp (old_reg_params, new_reg_params, sizeof (WLBS_REG_PARAMS)) == 0)
  1456. {
  1457. //
  1458. // No changes
  1459. //
  1460. TRACE_VERB("<-%!FUNC! no changes; return %d", WLBS_OK);
  1461. return WLBS_OK;
  1462. }
  1463. if (ParamWriteReg(AdapterGuid, new_reg_params) == false)
  1464. {
  1465. TRACE_CRIT("%!FUNC! registry write for parameters failed");
  1466. TRACE_VERB("<-%!FUNC! return %d", WLBS_REG_ERROR);
  1467. return WLBS_REG_ERROR;
  1468. }
  1469. /* No errors so far, so set the global flags reload_required and reboot_required
  1470. * depending on which fields have been changed between new_reg_params and old_params.
  1471. */
  1472. *p_reload_required = true;
  1473. /* Adapter reload is required if multicast_support option is changed, or
  1474. * if the user specifies a different mac address or cluster ip address
  1475. */
  1476. if (old_reg_params->mcast_support != new_reg_params->mcast_support ||
  1477. _tcsicmp(old_reg_params->cl_mac_addr, new_reg_params->cl_mac_addr) != 0 ||
  1478. _tcscmp(old_reg_params->cl_ip_addr, new_reg_params->cl_ip_addr) != 0) {
  1479. *p_notify_adapter_required = true;
  1480. //
  1481. // if new_reg_params -> mcast_support then remove mac addr, otherwise write mac addr
  1482. //
  1483. if (RegChangeNetworkAddress (AdapterGuid, new_reg_params->cl_mac_addr, new_reg_params->mcast_support) == false) {
  1484. TRACE_CRIT("%!FUNC! RegChangeNetworkAddress failed");
  1485. }
  1486. }
  1487. /* Write the changes to the structure old_values
  1488. * This copying is done only after all the data has been written into the registry
  1489. * Otherwise, the structure old_values would retain the previous values.
  1490. */
  1491. memcpy(old_reg_params, new_reg_params, sizeof (WLBS_REG_PARAMS));
  1492. TRACE_VERB("<-%!FUNC! return %d", WLBS_OK);
  1493. return WLBS_OK;
  1494. }
  1495. //+----------------------------------------------------------------------------
  1496. //
  1497. // Function: ParamWriteReg
  1498. //
  1499. // Description: Write cluster settings to registry
  1500. //
  1501. // Arguments: const GUID& AdapterGuid -
  1502. // PWLBS_REG_PARAMS paramp -
  1503. //
  1504. // Returns: bool -
  1505. //
  1506. // History: fengsun Created Header 3/9/00
  1507. //
  1508. //+----------------------------------------------------------------------------
  1509. bool WINAPI ParamWriteReg(const GUID& AdapterGuid, PWLBS_REG_PARAMS paramp)
  1510. {
  1511. TRACE_VERB("->%!FUNC!");
  1512. HKEY bda_key = NULL;
  1513. HKEY key = NULL;
  1514. DWORD size;
  1515. LONG status;
  1516. DWORD disp, idx;
  1517. DWORD num_rules;
  1518. WLBS_PORT_RULE *port_rule;
  1519. HRESULT hresult;
  1520. if (!WlbsValidateParams(paramp))
  1521. goto error;
  1522. num_rules = paramp -> i_num_rules;
  1523. /* Generate the MAC address. */
  1524. ParamsGenerateMAC(paramp->cl_ip_addr, paramp->cl_mac_addr, ASIZECCH(paramp->cl_mac_addr), paramp->szMCastIpAddress, ASIZECCH(paramp->szMCastIpAddress), paramp->i_convert_mac,
  1525. paramp->mcast_support, paramp->fIGMPSupport, paramp->fIpToMCastIp);
  1526. WCHAR reg_path [PARAMS_MAX_STRING_SIZE];
  1527. WCHAR szAdapterGuid[128];
  1528. if (0 == StringFromGUID2(AdapterGuid, szAdapterGuid, sizeof(szAdapterGuid)/sizeof(szAdapterGuid[0])))
  1529. {
  1530. TRACE_CRIT("%!FUNC! guid is too large for string. Result is %ls", szAdapterGuid);
  1531. // This check was added for tracing. No abort was done previously on error, so don't do so now.
  1532. }
  1533. hresult = StringCbPrintf (reg_path, sizeof(reg_path), L"SYSTEM\\CurrentControlSet\\Services\\WLBS\\Parameters\\Interface\\%s",
  1534. szAdapterGuid);
  1535. if (FAILED(hresult))
  1536. {
  1537. TRACE_CRIT("%!FUNC! StringCbPrintf failed, Error code : 0x%x", HRESULT_CODE(hresult));
  1538. TRACE_VERB("<-%!FUNC! return false");
  1539. return FALSE;
  1540. }
  1541. status = RegCreateKeyEx (HKEY_LOCAL_MACHINE, reg_path, 0L, L"",
  1542. REG_OPTION_NON_VOLATILE,
  1543. KEY_ALL_ACCESS, NULL, & key, & disp);
  1544. if (status != ERROR_SUCCESS)
  1545. {
  1546. TRACE_CRIT("%!FUNC! RegCreateKeyEx for %ls failed with %d", reg_path, status);
  1547. TRACE_VERB("<-%!FUNC! return false");
  1548. return FALSE;
  1549. }
  1550. size = sizeof (paramp -> install_date);
  1551. status = RegSetValueEx (key, CVY_NAME_INSTALL_DATE, 0L, CVY_TYPE_INSTALL_DATE,
  1552. (LPBYTE) & paramp -> install_date, size);
  1553. if (status != ERROR_SUCCESS)
  1554. {
  1555. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_INSTALL_DATE, status);
  1556. goto error;
  1557. }
  1558. size = sizeof (paramp -> i_verify_date);
  1559. status = RegSetValueEx (key, CVY_NAME_VERIFY_DATE, 0L, CVY_TYPE_VERIFY_DATE,
  1560. (LPBYTE) & paramp -> i_verify_date, size);
  1561. if (status != ERROR_SUCCESS)
  1562. {
  1563. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_VERIFY_DATE, status);
  1564. goto error;
  1565. }
  1566. size = wcslen (paramp -> i_virtual_nic_name) * sizeof (WCHAR);
  1567. status = RegSetValueEx (key, CVY_NAME_VIRTUAL_NIC, 0L, CVY_TYPE_VIRTUAL_NIC,
  1568. (LPBYTE) paramp -> i_virtual_nic_name, size);
  1569. if (status != ERROR_SUCCESS)
  1570. {
  1571. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_VIRTUAL_NIC, status);
  1572. goto error;
  1573. }
  1574. size = sizeof (paramp -> host_priority);
  1575. status = RegSetValueEx (key, CVY_NAME_HOST_PRIORITY, 0L, CVY_TYPE_HOST_PRIORITY,
  1576. (LPBYTE) & paramp -> host_priority, size);
  1577. if (status != ERROR_SUCCESS)
  1578. {
  1579. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_HOST_PRIORITY, status);
  1580. goto error;
  1581. }
  1582. size = sizeof (paramp -> cluster_mode);
  1583. status = RegSetValueEx (key, CVY_NAME_CLUSTER_MODE, 0L, CVY_TYPE_CLUSTER_MODE,
  1584. (LPBYTE) & paramp -> cluster_mode, size);
  1585. if (status != ERROR_SUCCESS)
  1586. {
  1587. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_CLUSTER_MODE, status);
  1588. goto error;
  1589. }
  1590. size = sizeof (paramp -> persisted_states);
  1591. status = RegSetValueEx (key, CVY_NAME_PERSISTED_STATES, 0L, CVY_TYPE_PERSISTED_STATES,
  1592. (LPBYTE) & paramp -> persisted_states, size);
  1593. if (status != ERROR_SUCCESS)
  1594. {
  1595. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_PERSISTED_STATES, status);
  1596. goto error;
  1597. }
  1598. size = wcslen (paramp -> cl_mac_addr) * sizeof (WCHAR);
  1599. status = RegSetValueEx (key, CVY_NAME_NETWORK_ADDR, 0L, CVY_TYPE_NETWORK_ADDR,
  1600. (LPBYTE) paramp -> cl_mac_addr, size);
  1601. if (status != ERROR_SUCCESS)
  1602. {
  1603. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_NETWORK_ADDR, status);
  1604. goto error;
  1605. }
  1606. size = wcslen (paramp -> cl_ip_addr) * sizeof (WCHAR);
  1607. status = RegSetValueEx (key, CVY_NAME_CL_IP_ADDR, 0L, CVY_TYPE_CL_IP_ADDR,
  1608. (LPBYTE) paramp -> cl_ip_addr, size);
  1609. if (status != ERROR_SUCCESS)
  1610. {
  1611. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_CL_IP_ADDR, status);
  1612. goto error;
  1613. }
  1614. size = wcslen (paramp -> cl_net_mask) * sizeof (WCHAR);
  1615. status = RegSetValueEx (key, CVY_NAME_CL_NET_MASK, 0L, CVY_TYPE_CL_NET_MASK,
  1616. (LPBYTE) paramp -> cl_net_mask, size);
  1617. if (status != ERROR_SUCCESS)
  1618. {
  1619. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_CL_NET_MASK, status);
  1620. goto error;
  1621. }
  1622. size = wcslen (paramp -> ded_ip_addr) * sizeof (WCHAR);
  1623. status = RegSetValueEx (key, CVY_NAME_DED_IP_ADDR, 0L, CVY_TYPE_DED_IP_ADDR,
  1624. (LPBYTE) paramp -> ded_ip_addr, size);
  1625. if (status != ERROR_SUCCESS)
  1626. {
  1627. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_DED_IP_ADDR, status);
  1628. goto error;
  1629. }
  1630. size = wcslen (paramp -> ded_net_mask) * sizeof (WCHAR);
  1631. status = RegSetValueEx (key, CVY_NAME_DED_NET_MASK, 0L, CVY_TYPE_DED_NET_MASK,
  1632. (LPBYTE) paramp -> ded_net_mask, size);
  1633. if (status != ERROR_SUCCESS)
  1634. {
  1635. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_DED_NET_MASK, status);
  1636. goto error;
  1637. }
  1638. size = wcslen (paramp -> domain_name) * sizeof (WCHAR);
  1639. status = RegSetValueEx (key, CVY_NAME_DOMAIN_NAME, 0L, CVY_TYPE_DOMAIN_NAME,
  1640. (LPBYTE) paramp -> domain_name, size);
  1641. if (status != ERROR_SUCCESS)
  1642. {
  1643. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_DOMAIN_NAME, status);
  1644. goto error;
  1645. }
  1646. size = sizeof (paramp -> alive_period);
  1647. status = RegSetValueEx (key, CVY_NAME_ALIVE_PERIOD, 0L, CVY_TYPE_ALIVE_PERIOD,
  1648. (LPBYTE) & paramp -> alive_period, size);
  1649. if (status != ERROR_SUCCESS)
  1650. {
  1651. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_ALIVE_PERIOD, status);
  1652. goto error;
  1653. }
  1654. size = sizeof (paramp -> alive_tolerance);
  1655. status = RegSetValueEx (key, CVY_NAME_ALIVE_TOLER, 0L, CVY_TYPE_ALIVE_TOLER,
  1656. (LPBYTE) & paramp -> alive_tolerance, size);
  1657. if (status != ERROR_SUCCESS)
  1658. {
  1659. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_ALIVE_TOLER, status);
  1660. goto error;
  1661. }
  1662. size = sizeof (paramp -> num_actions);
  1663. status = RegSetValueEx (key, CVY_NAME_NUM_ACTIONS, 0L, CVY_TYPE_NUM_ACTIONS,
  1664. (LPBYTE) & paramp -> num_actions, size);
  1665. if (status != ERROR_SUCCESS)
  1666. {
  1667. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_NUM_ACTIONS, status);
  1668. goto error;
  1669. }
  1670. size = sizeof (paramp -> num_packets);
  1671. status = RegSetValueEx (key, CVY_NAME_NUM_PACKETS, 0L, CVY_TYPE_NUM_PACKETS,
  1672. (LPBYTE) & paramp -> num_packets, size);
  1673. if (status != ERROR_SUCCESS)
  1674. {
  1675. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_NUM_PACKETS, status);
  1676. goto error;
  1677. }
  1678. size = sizeof (paramp -> num_send_msgs);
  1679. status = RegSetValueEx (key, CVY_NAME_NUM_SEND_MSGS, 0L, CVY_TYPE_NUM_SEND_MSGS,
  1680. (LPBYTE) & paramp -> num_send_msgs, size);
  1681. if (status != ERROR_SUCCESS)
  1682. {
  1683. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_NUM_SEND_MSGS, status);
  1684. goto error;
  1685. }
  1686. size = sizeof (paramp -> dscr_per_alloc);
  1687. status = RegSetValueEx (key, CVY_NAME_DSCR_PER_ALLOC, 0L, CVY_TYPE_DSCR_PER_ALLOC,
  1688. (LPBYTE) & paramp -> dscr_per_alloc, size);
  1689. if (status != ERROR_SUCCESS)
  1690. {
  1691. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_DSCR_PER_ALLOC, status);
  1692. goto error;
  1693. }
  1694. size = sizeof (paramp -> tcp_dscr_timeout);
  1695. status = RegSetValueEx (key, CVY_NAME_TCP_TIMEOUT, 0L, CVY_TYPE_TCP_TIMEOUT,
  1696. (LPBYTE) & paramp -> tcp_dscr_timeout, size);
  1697. if (status != ERROR_SUCCESS)
  1698. {
  1699. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_TCP_TIMEOUT, status);
  1700. goto error;
  1701. }
  1702. size = sizeof (paramp -> ipsec_dscr_timeout);
  1703. status = RegSetValueEx (key, CVY_NAME_IPSEC_TIMEOUT, 0L, CVY_TYPE_IPSEC_TIMEOUT,
  1704. (LPBYTE) & paramp -> ipsec_dscr_timeout, size);
  1705. if (status != ERROR_SUCCESS)
  1706. {
  1707. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_IPSEC_TIMEOUT, status);
  1708. goto error;
  1709. }
  1710. size = sizeof (paramp -> filter_icmp);
  1711. status = RegSetValueEx (key, CVY_NAME_FILTER_ICMP, 0L, CVY_TYPE_FILTER_ICMP,
  1712. (LPBYTE) & paramp -> filter_icmp, size);
  1713. if (status != ERROR_SUCCESS)
  1714. {
  1715. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_FILTER_ICMP, status);
  1716. goto error;
  1717. }
  1718. size = sizeof (paramp -> max_dscr_allocs);
  1719. status = RegSetValueEx (key, CVY_NAME_MAX_DSCR_ALLOCS, 0L, CVY_TYPE_MAX_DSCR_ALLOCS,
  1720. (LPBYTE) & paramp -> max_dscr_allocs, size);
  1721. if (status != ERROR_SUCCESS)
  1722. {
  1723. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_MAX_DSCR_ALLOCS, status);
  1724. goto error;
  1725. }
  1726. size = sizeof (paramp -> i_scale_client);
  1727. status = RegSetValueEx (key, CVY_NAME_SCALE_CLIENT, 0L, CVY_TYPE_SCALE_CLIENT,
  1728. (LPBYTE) & paramp -> i_scale_client, size);
  1729. if (status != ERROR_SUCCESS)
  1730. {
  1731. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_SCALE_CLIENT, status);
  1732. goto error;
  1733. }
  1734. size = sizeof (paramp -> i_cleanup_delay);
  1735. status = RegSetValueEx (key, CVY_NAME_CLEANUP_DELAY, 0L, CVY_TYPE_CLEANUP_DELAY,
  1736. (LPBYTE) & paramp -> i_cleanup_delay, size);
  1737. if (status != ERROR_SUCCESS)
  1738. {
  1739. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_CLEANUP_DELAY, status);
  1740. goto error;
  1741. }
  1742. /* V1.1.1 */
  1743. size = sizeof (paramp -> i_nbt_support);
  1744. status = RegSetValueEx (key, CVY_NAME_NBT_SUPPORT, 0L, CVY_TYPE_NBT_SUPPORT,
  1745. (LPBYTE) & paramp -> i_nbt_support, size);
  1746. if (status != ERROR_SUCCESS)
  1747. {
  1748. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_NBT_SUPPORT, status);
  1749. goto error;
  1750. }
  1751. /* V1.3b */
  1752. size = sizeof (paramp -> mcast_support);
  1753. status = RegSetValueEx (key, CVY_NAME_MCAST_SUPPORT, 0L, CVY_TYPE_MCAST_SUPPORT,
  1754. (LPBYTE) & paramp -> mcast_support, size);
  1755. if (status != ERROR_SUCCESS)
  1756. {
  1757. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_MCAST_SUPPORT, status);
  1758. goto error;
  1759. }
  1760. size = sizeof (paramp -> i_mcast_spoof);
  1761. status = RegSetValueEx (key, CVY_NAME_MCAST_SPOOF, 0L, CVY_TYPE_MCAST_SPOOF,
  1762. (LPBYTE) & paramp -> i_mcast_spoof, size);
  1763. if (status != ERROR_SUCCESS)
  1764. {
  1765. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_MCAST_SPOOF, status);
  1766. goto error;
  1767. }
  1768. size = sizeof (paramp -> mask_src_mac);
  1769. status = RegSetValueEx (key, CVY_NAME_MASK_SRC_MAC, 0L, CVY_TYPE_MASK_SRC_MAC,
  1770. (LPBYTE) & paramp -> mask_src_mac, size);
  1771. if (status != ERROR_SUCCESS)
  1772. {
  1773. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_MASK_SRC_MAC, status);
  1774. goto error;
  1775. }
  1776. size = sizeof (paramp -> i_netmon_alive);
  1777. status = RegSetValueEx (key, CVY_NAME_NETMON_ALIVE, 0L, CVY_TYPE_NETMON_ALIVE,
  1778. (LPBYTE) & paramp -> i_netmon_alive, size);
  1779. if (status != ERROR_SUCCESS)
  1780. {
  1781. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_NETMON_ALIVE, status);
  1782. goto error;
  1783. }
  1784. size = sizeof (paramp -> i_ip_chg_delay);
  1785. status = RegSetValueEx (key, CVY_NAME_IP_CHG_DELAY, 0L, CVY_TYPE_IP_CHG_DELAY,
  1786. (LPBYTE) & paramp -> i_ip_chg_delay, size);
  1787. if (status != ERROR_SUCCESS)
  1788. {
  1789. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_IP_CHG_DELAY, status);
  1790. goto error;
  1791. }
  1792. size = sizeof (paramp -> i_convert_mac);
  1793. status = RegSetValueEx (key, CVY_NAME_CONVERT_MAC, 0L, CVY_TYPE_CONVERT_MAC,
  1794. (LPBYTE) & paramp -> i_convert_mac, size);
  1795. if (status != ERROR_SUCCESS)
  1796. {
  1797. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_CONVERT_MAC, status);
  1798. goto error;
  1799. }
  1800. size = sizeof (paramp -> i_num_rules);
  1801. status = RegSetValueEx (key, CVY_NAME_NUM_RULES, 0L, CVY_TYPE_NUM_RULES,
  1802. (LPBYTE) & paramp -> i_num_rules, size);
  1803. if (status != ERROR_SUCCESS)
  1804. {
  1805. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_NUM_RULES, status);
  1806. goto error;
  1807. }
  1808. //
  1809. // sort the rules before writing it to the registry
  1810. // EnumPortRules will take the rules from reg_data and return them in
  1811. // sorted order in the array itself
  1812. //
  1813. WlbsEnumPortRules (paramp, paramp -> i_port_rules, & num_rules);
  1814. ASSERT(paramp -> i_parms_ver == CVY_PARAMS_VERSION); // version should be upgrated in read
  1815. HKEY subkey;
  1816. // Delete all existing Port Rules
  1817. SHDeleteKey(key, CVY_NAME_PORT_RULES); // NOT Checking return value cos the key itself may not be present in which case, it will return error
  1818. // Create "PortRules" key
  1819. status = RegCreateKeyEx (key, CVY_NAME_PORT_RULES, 0L, L"", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, & subkey, & disp);
  1820. if (status != ERROR_SUCCESS)
  1821. {
  1822. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_PORT_RULES, status);
  1823. goto error;
  1824. }
  1825. bool fSpecificVipPortRuleFound = false;
  1826. idx = 1;
  1827. port_rule = paramp -> i_port_rules;
  1828. while(idx <= num_rules)
  1829. {
  1830. // Invalid port rules are placed at the end, So, once an invalid port rule is encountered, we are done
  1831. if (!port_rule->valid)
  1832. break;
  1833. HKEY rule_key;
  1834. wchar_t idx_str[8];
  1835. // Create the per port-rule key "1", "2", "3", ...etc
  1836. status = RegCreateKeyEx (subkey, _itow(idx, idx_str, 10), 0L, L"", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, & rule_key, & disp);
  1837. if (status != ERROR_SUCCESS)
  1838. {
  1839. TRACE_CRIT("%!FUNC! registry create for %ls failed with %d", idx_str, status);
  1840. goto error;
  1841. }
  1842. // Check if there was any specific-vip port rule
  1843. if (!fSpecificVipPortRuleFound && lstrcmpi(port_rule->virtual_ip_addr, CVY_DEF_ALL_VIP))
  1844. fSpecificVipPortRuleFound = true;
  1845. size = wcslen (port_rule -> virtual_ip_addr) * sizeof (WCHAR);
  1846. status = RegSetValueEx (rule_key, CVY_NAME_VIP, 0L, CVY_TYPE_VIP, (LPBYTE) port_rule->virtual_ip_addr, size);
  1847. if (status != ERROR_SUCCESS)
  1848. {
  1849. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_VIP, status);
  1850. goto error;
  1851. }
  1852. size = sizeof (port_rule ->start_port );
  1853. status = RegSetValueEx (rule_key, CVY_NAME_START_PORT, 0L, CVY_TYPE_START_PORT, (LPBYTE) &port_rule->start_port, size);
  1854. if (status != ERROR_SUCCESS)
  1855. {
  1856. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_START_PORT, status);
  1857. goto error;
  1858. }
  1859. size = sizeof (port_rule ->end_port );
  1860. status = RegSetValueEx (rule_key, CVY_NAME_END_PORT, 0L, CVY_TYPE_END_PORT, (LPBYTE) &port_rule->end_port, size);
  1861. if (status != ERROR_SUCCESS)
  1862. {
  1863. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_END_PORT, status);
  1864. goto error;
  1865. }
  1866. size = sizeof (port_rule ->code);
  1867. status = RegSetValueEx (rule_key, CVY_NAME_CODE, 0L, CVY_TYPE_CODE, (LPBYTE) &port_rule->code, size);
  1868. if (status != ERROR_SUCCESS)
  1869. {
  1870. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_CODE, status);
  1871. goto error;
  1872. }
  1873. size = sizeof (port_rule->mode);
  1874. status = RegSetValueEx (rule_key, CVY_NAME_MODE, 0L, CVY_TYPE_MODE, (LPBYTE) &port_rule->mode, size);
  1875. if (status != ERROR_SUCCESS)
  1876. {
  1877. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_MODE, status);
  1878. goto error;
  1879. }
  1880. size = sizeof (port_rule->protocol);
  1881. status = RegSetValueEx (rule_key, CVY_NAME_PROTOCOL, 0L, CVY_TYPE_PROTOCOL, (LPBYTE) &port_rule->protocol, size);
  1882. if (status != ERROR_SUCCESS)
  1883. {
  1884. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_PROTOCOL, status);
  1885. goto error;
  1886. }
  1887. DWORD EqualLoad, Affinity;
  1888. switch (port_rule->mode)
  1889. {
  1890. case CVY_MULTI :
  1891. EqualLoad = port_rule->mode_data.multi.equal_load;
  1892. size = sizeof (EqualLoad);
  1893. status = RegSetValueEx (rule_key, CVY_NAME_EQUAL_LOAD, 0L, CVY_TYPE_EQUAL_LOAD, (LPBYTE) &EqualLoad, size);
  1894. if (status != ERROR_SUCCESS)
  1895. {
  1896. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_EQUAL_LOAD, status);
  1897. goto error;
  1898. }
  1899. Affinity = port_rule->mode_data.multi.affinity;
  1900. size = sizeof (Affinity);
  1901. status = RegSetValueEx (rule_key, CVY_NAME_AFFINITY, 0L, CVY_TYPE_AFFINITY, (LPBYTE) &Affinity, size);
  1902. if (status != ERROR_SUCCESS)
  1903. {
  1904. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_AFFINITY, status);
  1905. goto error;
  1906. }
  1907. size = sizeof (port_rule->mode_data.multi.load);
  1908. status = RegSetValueEx (rule_key, CVY_NAME_LOAD, 0L, CVY_TYPE_LOAD, (LPBYTE) &(port_rule->mode_data.multi.load), size);
  1909. if (status != ERROR_SUCCESS)
  1910. {
  1911. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_LOAD, status);
  1912. goto error;
  1913. }
  1914. break;
  1915. case CVY_SINGLE :
  1916. size = sizeof (port_rule->mode_data.single.priority);
  1917. status = RegSetValueEx (rule_key, CVY_NAME_PRIORITY, 0L, CVY_TYPE_PRIORITY, (LPBYTE) &(port_rule->mode_data.single.priority), size);
  1918. if (status != ERROR_SUCCESS)
  1919. {
  1920. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_PRIORITY, status);
  1921. goto error;
  1922. }
  1923. break;
  1924. default:
  1925. break;
  1926. }
  1927. if (ERROR_SUCCESS != RegCloseKey(rule_key))
  1928. {
  1929. TRACE_CRIT("%!FUNC! error closing registry key of individual port rules");
  1930. }
  1931. port_rule++;
  1932. idx++;
  1933. }
  1934. if (ERROR_SUCCESS != RegCloseKey(subkey))
  1935. {
  1936. TRACE_CRIT("%!FUNC! error closing %ls registry key",CVY_NAME_PORT_RULES);
  1937. }
  1938. // If there is a specific-vip port rule, write that info on to the registry
  1939. if (fSpecificVipPortRuleFound)
  1940. paramp -> i_effective_version = CVY_VERSION_FULL;
  1941. else
  1942. paramp -> i_effective_version = CVY_NT40_VERSION_FULL;
  1943. size = sizeof (paramp -> i_effective_version);
  1944. status = RegSetValueEx (key, CVY_NAME_EFFECTIVE_VERSION, 0L, CVY_TYPE_EFFECTIVE_VERSION,
  1945. (LPBYTE) & paramp -> i_effective_version, size);
  1946. if (status != ERROR_SUCCESS)
  1947. {
  1948. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_EFFECTIVE_VERSION, status);
  1949. goto error;
  1950. }
  1951. size = wcslen (paramp -> i_license_key) * sizeof (WCHAR);
  1952. status = RegSetValueEx (key, CVY_NAME_LICENSE_KEY, 0L, CVY_TYPE_LICENSE_KEY,
  1953. (LPBYTE) paramp -> i_license_key, size);
  1954. if (status != ERROR_SUCCESS)
  1955. {
  1956. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_LICENSE_KEY, status);
  1957. goto error;
  1958. }
  1959. size = sizeof (paramp -> i_rmt_password);
  1960. status = RegSetValueEx (key, CVY_NAME_RMT_PASSWORD, 0L, CVY_TYPE_RMT_PASSWORD,
  1961. (LPBYTE) & paramp -> i_rmt_password, size);
  1962. if (status != ERROR_SUCCESS)
  1963. {
  1964. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_RMT_PASSWORD, status);
  1965. goto error;
  1966. }
  1967. size = sizeof (paramp -> i_rct_password);
  1968. status = RegSetValueEx (key, CVY_NAME_RCT_PASSWORD, 0L, CVY_TYPE_RCT_PASSWORD,
  1969. (LPBYTE) & paramp -> i_rct_password, size);
  1970. if (status != ERROR_SUCCESS)
  1971. {
  1972. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_RCT_PASSWORD, status);
  1973. goto error;
  1974. }
  1975. size = sizeof (paramp -> rct_port);
  1976. status = RegSetValueEx (key, CVY_NAME_RCT_PORT, 0L, CVY_TYPE_RCT_PORT,
  1977. (LPBYTE) & paramp -> rct_port, size);
  1978. if (status != ERROR_SUCCESS)
  1979. {
  1980. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_RCT_PORT, status);
  1981. goto error;
  1982. }
  1983. size = sizeof (paramp -> rct_enabled);
  1984. status = RegSetValueEx (key, CVY_NAME_RCT_ENABLED, 0L, CVY_TYPE_RCT_ENABLED,
  1985. (LPBYTE) & paramp -> rct_enabled, size);
  1986. if (status != ERROR_SUCCESS)
  1987. {
  1988. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_RCT_ENABLED, status);
  1989. goto error;
  1990. }
  1991. size = sizeof (paramp -> identity_period);
  1992. status = RegSetValueEx (key, CVY_NAME_ID_HB_PERIOD, 0L, CVY_TYPE_ID_HB_PERIOD,
  1993. (LPBYTE) & paramp -> identity_period, size);
  1994. if (status != ERROR_SUCCESS)
  1995. {
  1996. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_ID_HB_PERIOD, status);
  1997. goto error;
  1998. }
  1999. size = sizeof (paramp -> identity_enabled);
  2000. status = RegSetValueEx (key, CVY_NAME_ID_HB_ENABLED, 0L, CVY_TYPE_ID_HB_ENABLED,
  2001. (LPBYTE) & paramp -> identity_enabled, size);
  2002. if (status != ERROR_SUCCESS)
  2003. {
  2004. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_ID_HB_ENABLED, status);
  2005. goto error;
  2006. }
  2007. //
  2008. // IGMP support registry entries
  2009. //
  2010. status = RegSetValueEx (key, CVY_NAME_IGMP_SUPPORT, 0L, CVY_TYPE_IGMP_SUPPORT,
  2011. (LPBYTE) & paramp->fIGMPSupport, sizeof (paramp->fIGMPSupport));
  2012. if (status != ERROR_SUCCESS)
  2013. {
  2014. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_IGMP_SUPPORT, status);
  2015. goto error;
  2016. }
  2017. status = RegSetValueEx (key, CVY_NAME_MCAST_IP_ADDR, 0L, CVY_TYPE_MCAST_IP_ADDR, (LPBYTE) paramp->szMCastIpAddress,
  2018. lstrlen (paramp->szMCastIpAddress)* sizeof(paramp->szMCastIpAddress[0]));
  2019. if (status != ERROR_SUCCESS)
  2020. {
  2021. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_MCAST_IP_ADDR, status);
  2022. goto error;
  2023. }
  2024. status = RegSetValueEx (key, CVY_NAME_IP_TO_MCASTIP, 0L, CVY_TYPE_IP_TO_MCASTIP,
  2025. (LPBYTE) & paramp->fIpToMCastIp, sizeof (paramp->fIpToMCastIp));
  2026. if (status != ERROR_SUCCESS)
  2027. {
  2028. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_IP_TO_MCASTIP, status);
  2029. goto error;
  2030. }
  2031. /* If teaming is active on this adapter, then create a subkey to house the BDA teaming configuration and fill it in. */
  2032. if (paramp->bda_teaming.active) {
  2033. /* Attempt to create the registry key. */
  2034. if (!(bda_key = RegCreateWlbsBDASettings(AdapterGuid)))
  2035. {
  2036. TRACE_CRIT("%!FUNC! registry create for bda settings failed");
  2037. goto error;
  2038. }
  2039. /* Set the team ID - if it fails, bail out. */
  2040. status = RegSetValueEx(bda_key, CVY_NAME_BDA_TEAM_ID, 0L, CVY_TYPE_BDA_TEAM_ID, (LPBYTE) paramp->bda_teaming.team_id,
  2041. lstrlen(paramp->bda_teaming.team_id) * sizeof(paramp->bda_teaming.team_id[0]));
  2042. if (status != ERROR_SUCCESS)
  2043. {
  2044. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_BDA_TEAM_ID, status);
  2045. goto bda_error;
  2046. }
  2047. /* Set the master status - if it fails, bail out. */
  2048. status = RegSetValueEx(bda_key, CVY_NAME_BDA_MASTER, 0L, CVY_TYPE_BDA_MASTER,
  2049. (LPBYTE)&paramp->bda_teaming.master, sizeof (paramp->bda_teaming.master));
  2050. if (status != ERROR_SUCCESS)
  2051. {
  2052. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_BDA_MASTER, status);
  2053. goto bda_error;
  2054. }
  2055. /* Set the reverse hashing flag - if it fails, bail out. */
  2056. status = RegSetValueEx(bda_key, CVY_NAME_BDA_REVERSE_HASH, 0L, CVY_TYPE_BDA_REVERSE_HASH,
  2057. (LPBYTE)&paramp->bda_teaming.reverse_hash, sizeof (paramp->bda_teaming.reverse_hash));
  2058. if (status != ERROR_SUCCESS)
  2059. {
  2060. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_BDA_REVERSE_HASH, status);
  2061. goto bda_error;
  2062. }
  2063. RegCloseKey(bda_key);
  2064. } else {
  2065. /* Delte the registry key and ignore the return value - the key may not even exist. */
  2066. if (!RegDeleteWlbsBDASettings(AdapterGuid))
  2067. {
  2068. // Make this an INFO message since it is possible that the key may not exist
  2069. TRACE_INFO("%!FUNC! registry delete for bda settings failed");
  2070. }
  2071. }
  2072. //
  2073. // Create an empty string if VirtualNICName does not exist
  2074. //
  2075. WCHAR virtual_nic_name[CVY_MAX_CLUSTER_NIC + 1];
  2076. size = sizeof(virtual_nic_name);
  2077. status = RegQueryValueEx (key, CVY_NAME_VIRTUAL_NIC, 0L, NULL,
  2078. (LPBYTE)virtual_nic_name, & size);
  2079. if (status != ERROR_SUCCESS)
  2080. {
  2081. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d", CVY_NAME_VIRTUAL_NIC, status);
  2082. virtual_nic_name [0] = 0;
  2083. size = wcslen (virtual_nic_name) * sizeof (WCHAR);
  2084. status = RegSetValueEx (key, CVY_NAME_VIRTUAL_NIC, 0L, CVY_TYPE_VIRTUAL_NIC,
  2085. (LPBYTE) virtual_nic_name, size);
  2086. if (status != ERROR_SUCCESS)
  2087. {
  2088. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_VIRTUAL_NIC, status);
  2089. }
  2090. }
  2091. /* lastly write the version number */
  2092. size = sizeof (paramp -> i_parms_ver);
  2093. status = RegSetValueEx (key, CVY_NAME_VERSION, 0L, CVY_TYPE_VERSION,
  2094. (LPBYTE) & paramp -> i_parms_ver, size);
  2095. if (status != ERROR_SUCCESS)
  2096. {
  2097. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_VERSION, status);
  2098. goto error;
  2099. }
  2100. if (ERROR_SUCCESS != RegCloseKey(key))
  2101. {
  2102. TRACE_CRIT("%!FUNC! error closing registry");
  2103. }
  2104. TRACE_VERB("<-%!FUNC! return true");
  2105. return TRUE;
  2106. error:
  2107. if (ERROR_SUCCESS != RegCloseKey(key))
  2108. {
  2109. TRACE_CRIT("%!FUNC! error closing registry");
  2110. }
  2111. TRACE_VERB("<-%!FUNC! return false");
  2112. return FALSE;
  2113. bda_error:
  2114. if (ERROR_SUCCESS != RegCloseKey(bda_key))
  2115. {
  2116. TRACE_CRIT("%!FUNC! error closing registry");
  2117. }
  2118. TRACE_VERB("<-%!FUNC! return false");
  2119. goto error;
  2120. }
  2121. //+----------------------------------------------------------------------------
  2122. //
  2123. // Function: ParamCommitChanges
  2124. //
  2125. // Description: Notify wlbs driver or nic driver to pick up the changes
  2126. //
  2127. // Arguments: Adapter GUID, Handle to NLB driver, Cluster IP Address (filled on return),
  2128. // Dedicated IP Address (filled on return), reload_required flag, mac_addr changeg flag
  2129. //
  2130. // Returns: DWORD -
  2131. //
  2132. // History: KarthicN Created 08/28/01
  2133. //
  2134. //
  2135. //+----------------------------------------------------------------------------
  2136. DWORD ParamCommitChanges(const GUID& AdapterGuid,
  2137. HANDLE hDeviceWlbs,
  2138. DWORD& cl_addr,
  2139. DWORD& ded_addr,
  2140. bool * p_reload_required,
  2141. bool * p_notify_adapter_required)
  2142. {
  2143. TRACE_VERB("->%!FUNC!");
  2144. LONG status;
  2145. // Read the cluster IP address and the dedicated IP address from the
  2146. // registry and update the global variables.
  2147. // Always update the cluster IP address and the dedicated IP address
  2148. if (!RegReadAdapterIp(AdapterGuid, cl_addr, ded_addr))
  2149. {
  2150. TRACE_CRIT("%!FUNC! failed reading cluster and dedicate IP addresses from registry");
  2151. // This check was added for tracing. No abort was done previously on error, so don't do so now.
  2152. }
  2153. /* Check if the driver requires a reload or not. If not, then simply return */
  2154. if (*p_reload_required == false)
  2155. {
  2156. TRACE_VERB("<-%!FUNC! no reload required. return %d", WLBS_OK);
  2157. return WLBS_OK;
  2158. }
  2159. status = NotifyDriverConfigChanges(hDeviceWlbs, AdapterGuid);
  2160. if (ERROR_SUCCESS != status)
  2161. {
  2162. TRACE_CRIT("%!FUNC! NotifyDriverConfigChanges failed with %d", status);
  2163. // This check was added for tracing. No abort was done previously on error, so don't do so now.
  2164. return status;
  2165. }
  2166. *p_reload_required = false; /* reset the flag */
  2167. if (*p_notify_adapter_required)
  2168. {
  2169. *p_notify_adapter_required = false;
  2170. /* The NIC card name for the cluster. */
  2171. WCHAR driver_name[CVY_STR_SIZE];
  2172. ZeroMemory(driver_name, sizeof(driver_name));
  2173. /* Get the driver name from the GUID. */
  2174. GetDriverNameFromGUID(AdapterGuid, driver_name, CVY_STR_SIZE);
  2175. /* No longer disable and enable the adapter, since this function never gets called on bind or unbind.
  2176. For other cases, prop change is all that is needed */
  2177. TRACE_INFO("%!FUNC! changing properties of adapter");
  2178. NotifyAdapterAddressChangeEx(driver_name, AdapterGuid, true);
  2179. }
  2180. TRACE_VERB("<-%!FUNC! return %d", WLBS_OK);
  2181. return WLBS_OK;
  2182. }
  2183. //+----------------------------------------------------------------------------
  2184. //
  2185. // Function: ParamDeleteReg
  2186. //
  2187. // Description: Delete the registry settings
  2188. //
  2189. // Arguments: IN const WCHAR* pszInterface -
  2190. //
  2191. // Returns: DWORD WINAPI -
  2192. //
  2193. // History: fengsun Created Header 1/22/00
  2194. //
  2195. //+----------------------------------------------------------------------------
  2196. bool WINAPI ParamDeleteReg(const GUID& AdapterGuid, bool fDeleteObsoleteEntries)
  2197. {
  2198. TRACE_VERB("->%!FUNC! pass");
  2199. WCHAR reg_path [PARAMS_MAX_STRING_SIZE];
  2200. LONG status;
  2201. HRESULT hresult;
  2202. WCHAR szAdapterGuid[128];
  2203. if (0 == StringFromGUID2(AdapterGuid, szAdapterGuid, sizeof(szAdapterGuid)/sizeof(szAdapterGuid[0])))
  2204. {
  2205. TRACE_CRIT("%!FUNC! guid is too large for string. Result is %ls", szAdapterGuid);
  2206. // This check was added for tracing. No abort was done previously on error, so don't do so now.
  2207. }
  2208. hresult = StringCbPrintf (reg_path, sizeof(reg_path), L"SYSTEM\\CurrentControlSet\\Services\\WLBS\\Parameters\\Interface\\%s",
  2209. szAdapterGuid);
  2210. if (FAILED(hresult))
  2211. {
  2212. TRACE_CRIT("%!FUNC! StringCbPrintf failed, Error code : 0x%x", HRESULT_CODE(hresult));
  2213. TRACE_VERB("<-%!FUNC! return false");
  2214. return FALSE;
  2215. }
  2216. if (fDeleteObsoleteEntries)
  2217. {
  2218. TRACE_INFO("%!FUNC! deleting obsolete registry entries");
  2219. HKEY hkey;
  2220. // Delete Port Rules in Binary format
  2221. status = RegOpenKeyEx (HKEY_LOCAL_MACHINE, reg_path, 0L, KEY_ALL_ACCESS, &hkey);
  2222. if (status == ERROR_SUCCESS)
  2223. {
  2224. status = RegDeleteValue(hkey, CVY_NAME_OLD_PORT_RULES);
  2225. if (ERROR_SUCCESS != status)
  2226. {
  2227. TRACE_CRIT("%!FUNC! registry delete of %ls failed with %d. Skipping it.", CVY_NAME_OLD_PORT_RULES, status);
  2228. // This check was added for tracing. No abort was done previously on error, so don't do so now.
  2229. }
  2230. status = RegCloseKey(hkey);
  2231. if (ERROR_SUCCESS != status)
  2232. {
  2233. TRACE_CRIT("%!FUNC! closing registry failed with %d", status);
  2234. }
  2235. }
  2236. else
  2237. {
  2238. TRACE_CRIT("%!FUNC! registry open for %ls failed with %d. Skipping it.", reg_path, status);
  2239. }
  2240. // Delete Win2k entries, Enumerate & delete values
  2241. hresult = StringCbPrintf (reg_path, sizeof(reg_path), L"SYSTEM\\CurrentControlSet\\Services\\WLBS\\Parameters");
  2242. if (FAILED(hresult))
  2243. {
  2244. TRACE_CRIT("%!FUNC! StringCbPrintf failed, Error code : 0x%x", HRESULT_CODE(hresult));
  2245. TRACE_VERB("<-%!FUNC! return false");
  2246. return FALSE;
  2247. }
  2248. status = RegOpenKeyEx (HKEY_LOCAL_MACHINE, reg_path, 0L, KEY_ALL_ACCESS, &hkey);
  2249. if (status == ERROR_SUCCESS)
  2250. {
  2251. DWORD Index, ValueNameSize;
  2252. WCHAR ValueName [PARAMS_MAX_STRING_SIZE];
  2253. Index = 0;
  2254. ValueNameSize = PARAMS_MAX_STRING_SIZE;
  2255. while (RegEnumValue(hkey, Index++, ValueName, &ValueNameSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
  2256. {
  2257. status = RegDeleteValue(hkey, ValueName);
  2258. if (ERROR_SUCCESS != status)
  2259. {
  2260. TRACE_CRIT("%!FUNC! registry delete of %ls failed with %d. Skipping it.", ValueName, status);
  2261. // This check was added for tracing. No abort was done previously on error, so don't do so now.
  2262. }
  2263. }
  2264. status = RegCloseKey(hkey);
  2265. if (ERROR_SUCCESS != status)
  2266. {
  2267. TRACE_CRIT("%!FUNC! closing registry failed with %d", status);
  2268. }
  2269. }
  2270. else
  2271. {
  2272. TRACE_CRIT("%!FUNC! registry open for %ls failed with %d. Skipping it.", reg_path, status);
  2273. }
  2274. }
  2275. else
  2276. {
  2277. TRACE_INFO("%!FUNC! deleting %ls", reg_path);
  2278. DWORD dwRet = RegDeleteKey(HKEY_LOCAL_MACHINE, reg_path);
  2279. if (dwRet != ERROR_SUCCESS)
  2280. {
  2281. TRACE_CRIT("%!FUNC! registry delete of %ls failed with %d", reg_path, dwRet);
  2282. TRACE_VERB("->%!FUNC! fail");
  2283. return false;
  2284. }
  2285. }
  2286. TRACE_VERB("<-%!FUNC! pass");
  2287. return true;
  2288. } /* end Params_delete */
  2289. //+----------------------------------------------------------------------------
  2290. //
  2291. // Function: ParamSetDefaults
  2292. //
  2293. // Description: Set default settings
  2294. //
  2295. // Arguments: PWLBS_REG_PARAMS reg_data -
  2296. //
  2297. // Returns: DWORD -
  2298. //
  2299. // History: fengsun Created Header 3/9/00
  2300. //
  2301. //+----------------------------------------------------------------------------
  2302. DWORD WINAPI ParamSetDefaults(PWLBS_REG_PARAMS reg_data)
  2303. {
  2304. reg_data -> struct_version = WLBS_REG_PARAMS_VERSION;
  2305. reg_data -> install_date = 0;
  2306. reg_data -> i_verify_date = 0;
  2307. // reg_data -> cluster_nic_name [0] = _TEXT('\0');
  2308. reg_data -> i_parms_ver = CVY_DEF_VERSION;
  2309. reg_data -> i_virtual_nic_name [0] = _TEXT('\0');
  2310. reg_data -> host_priority = CVY_DEF_HOST_PRIORITY;
  2311. reg_data -> cluster_mode = CVY_DEF_CLUSTER_MODE;
  2312. reg_data -> persisted_states = CVY_DEF_PERSISTED_STATES;
  2313. StringCbCopy (reg_data -> cl_mac_addr, sizeof(reg_data -> cl_mac_addr), CVY_DEF_NETWORK_ADDR);
  2314. StringCbCopy (reg_data -> cl_ip_addr, sizeof(reg_data -> cl_ip_addr), CVY_DEF_CL_IP_ADDR);
  2315. StringCbCopy (reg_data -> cl_net_mask, sizeof(reg_data -> cl_net_mask), CVY_DEF_CL_NET_MASK);
  2316. StringCbCopy (reg_data -> ded_ip_addr, sizeof(reg_data -> ded_ip_addr), CVY_DEF_DED_IP_ADDR);
  2317. StringCbCopy (reg_data -> ded_net_mask, sizeof(reg_data -> ded_net_mask), CVY_DEF_DED_NET_MASK);
  2318. StringCbCopy (reg_data -> domain_name, sizeof(reg_data -> domain_name), CVY_DEF_DOMAIN_NAME);
  2319. reg_data -> alive_period = CVY_DEF_ALIVE_PERIOD;
  2320. reg_data -> alive_tolerance = CVY_DEF_ALIVE_TOLER;
  2321. reg_data -> num_actions = CVY_DEF_NUM_ACTIONS;
  2322. reg_data -> num_packets = CVY_DEF_NUM_PACKETS;
  2323. reg_data -> num_send_msgs = CVY_DEF_NUM_SEND_MSGS;
  2324. reg_data -> dscr_per_alloc = CVY_DEF_DSCR_PER_ALLOC;
  2325. reg_data -> tcp_dscr_timeout = CVY_DEF_TCP_TIMEOUT;
  2326. reg_data -> ipsec_dscr_timeout = CVY_DEF_IPSEC_TIMEOUT;
  2327. reg_data -> filter_icmp = CVY_DEF_FILTER_ICMP;
  2328. reg_data -> max_dscr_allocs = CVY_DEF_MAX_DSCR_ALLOCS;
  2329. reg_data -> i_scale_client = CVY_DEF_SCALE_CLIENT;
  2330. reg_data -> i_cleanup_delay = CVY_DEF_CLEANUP_DELAY;
  2331. reg_data -> i_ip_chg_delay = CVY_DEF_IP_CHG_DELAY;
  2332. reg_data -> i_nbt_support = CVY_DEF_NBT_SUPPORT;
  2333. reg_data -> mcast_support = CVY_DEF_MCAST_SUPPORT;
  2334. reg_data -> i_mcast_spoof = CVY_DEF_MCAST_SPOOF;
  2335. reg_data -> mask_src_mac = CVY_DEF_MASK_SRC_MAC;
  2336. reg_data -> i_netmon_alive = CVY_DEF_NETMON_ALIVE;
  2337. reg_data -> i_effective_version = CVY_NT40_VERSION_FULL;
  2338. reg_data -> i_convert_mac = CVY_DEF_CONVERT_MAC;
  2339. reg_data -> i_num_rules = 0;
  2340. memset (reg_data -> i_port_rules, 0, sizeof (WLBS_PORT_RULE) * WLBS_MAX_RULES);
  2341. StringCbCopy (reg_data -> i_license_key, sizeof(reg_data -> i_license_key), CVY_DEF_LICENSE_KEY);
  2342. reg_data -> i_rmt_password = CVY_DEF_RMT_PASSWORD;
  2343. reg_data -> i_rct_password = CVY_DEF_RCT_PASSWORD;
  2344. reg_data -> rct_port = CVY_DEF_RCT_PORT;
  2345. reg_data -> rct_enabled = CVY_DEF_RCT_ENABLED;
  2346. reg_data -> i_max_hosts = CVY_MAX_HOSTS;
  2347. reg_data -> i_max_rules = CVY_MAX_USABLE_RULES;
  2348. reg_data -> identity_period = CVY_DEF_ID_HB_PERIOD;
  2349. reg_data -> identity_enabled = CVY_DEF_ID_HB_ENABLED;
  2350. reg_data -> fIGMPSupport = CVY_DEF_IGMP_SUPPORT;
  2351. StringCbCopy(reg_data -> szMCastIpAddress, sizeof(reg_data -> szMCastIpAddress), CVY_DEF_MCAST_IP_ADDR);
  2352. reg_data -> fIpToMCastIp = CVY_DEF_IP_TO_MCASTIP;
  2353. reg_data->bda_teaming.active = CVY_DEF_BDA_ACTIVE;
  2354. reg_data->bda_teaming.master = CVY_DEF_BDA_MASTER;
  2355. reg_data->bda_teaming.reverse_hash = CVY_DEF_BDA_REVERSE_HASH;
  2356. reg_data->bda_teaming.team_id[0] = CVY_DEF_BDA_TEAM_ID;
  2357. reg_data -> i_num_rules = 1;
  2358. // fill in the first port rule.
  2359. StringCbCopy (reg_data->i_port_rules[0].virtual_ip_addr, sizeof(reg_data->i_port_rules[0].virtual_ip_addr), CVY_DEF_ALL_VIP);
  2360. reg_data -> i_port_rules [0] . start_port = CVY_DEF_PORT_START;
  2361. reg_data -> i_port_rules [0] . end_port = CVY_DEF_PORT_END;
  2362. reg_data -> i_port_rules [0] . valid = TRUE;
  2363. reg_data -> i_port_rules [0] . mode = CVY_DEF_MODE;
  2364. reg_data -> i_port_rules [0] . mode_data . multi . equal_load = TRUE;
  2365. reg_data -> i_port_rules [0] . mode_data . multi . affinity = CVY_DEF_AFFINITY;
  2366. reg_data -> i_port_rules [0] . mode_data . multi . load = CVY_DEF_LOAD;
  2367. reg_data -> i_port_rules [0] . protocol = CVY_DEF_PROTOCOL;
  2368. CVY_RULE_CODE_SET(& reg_data -> i_port_rules [0]);
  2369. return WLBS_OK;
  2370. }
  2371. EXTERN_C DWORD WINAPI WlbsGetNumPortRules
  2372. (
  2373. const PWLBS_REG_PARAMS reg_data
  2374. )
  2375. {
  2376. if (reg_data == NULL)
  2377. return WLBS_BAD_PARAMS;
  2378. return reg_data -> i_num_rules;
  2379. } /* end WlbsGetNumPortRules */
  2380. EXTERN_C DWORD WINAPI WlbsGetEffectiveVersion
  2381. (
  2382. const PWLBS_REG_PARAMS reg_data
  2383. )
  2384. {
  2385. if (reg_data == NULL)
  2386. return WLBS_BAD_PARAMS;
  2387. return reg_data -> i_effective_version;
  2388. } /* end WlbsGetEffectiveVersion */
  2389. EXTERN_C DWORD WINAPI WlbsEnumPortRules
  2390. (
  2391. const PWLBS_REG_PARAMS reg_data,
  2392. PWLBS_PORT_RULE rules,
  2393. PDWORD num_rules
  2394. )
  2395. {
  2396. TRACE_VERB("->%!FUNC!");
  2397. DWORD count_rules, i, index;
  2398. DWORD lowest_vip, lowest_port;
  2399. BOOL array_flags [WLBS_MAX_RULES];
  2400. WLBS_PORT_RULE sorted_rules [WLBS_MAX_RULES];
  2401. if ((reg_data == NULL) || (num_rules == NULL))
  2402. {
  2403. TRACE_CRIT("%!FUNC! bad input parameter for registry data or output buffer size");
  2404. TRACE_VERB("<-%!FUNC! return %d", WLBS_BAD_PARAMS);
  2405. return WLBS_BAD_PARAMS;
  2406. }
  2407. if (*num_rules == 0)
  2408. rules = NULL;
  2409. /* this array is used for keeping track of which rules have already been retrieved */
  2410. /* This is needed since the rules are to be retrieved in the sorted order */
  2411. memset ( array_flags, 0, sizeof(BOOL) * WLBS_MAX_RULES );
  2412. count_rules = 0;
  2413. while ((count_rules < *num_rules) && (count_rules < reg_data -> i_num_rules))
  2414. {
  2415. i = 0;
  2416. /* find the first rule that has not been retrieved */
  2417. while ((! reg_data -> i_port_rules [i] . valid) || array_flags [i])
  2418. {
  2419. i++;
  2420. }
  2421. lowest_vip = htonl(IpAddressFromAbcdWsz(reg_data -> i_port_rules [i] . virtual_ip_addr));
  2422. lowest_port = reg_data -> i_port_rules [i] . start_port;
  2423. index = i;
  2424. /* Compare that rule with the other non-retrieved rules to get the rule with the
  2425. lowest VIP & start_port */
  2426. i++;
  2427. while (i < WLBS_MAX_RULES)
  2428. {
  2429. if (reg_data -> i_port_rules [i] . valid && ( ! array_flags [i] ))
  2430. {
  2431. DWORD current_vip = htonl(IpAddressFromAbcdWsz(reg_data -> i_port_rules [i] . virtual_ip_addr));
  2432. if ((current_vip < lowest_vip)
  2433. || ((current_vip == lowest_vip) && (reg_data -> i_port_rules [i] . start_port < lowest_port)))
  2434. {
  2435. lowest_vip = current_vip;
  2436. lowest_port = reg_data -> i_port_rules [i] . start_port;
  2437. index = i;
  2438. }
  2439. }
  2440. i++;
  2441. }
  2442. /* The array_flags [i] element is set to TRUE if the rule is retrieved */
  2443. array_flags [index] = TRUE;
  2444. sorted_rules [count_rules] = reg_data -> i_port_rules [index];
  2445. count_rules ++;
  2446. }
  2447. /* write the sorted rules back into the return array */
  2448. TRACE_VERB("%!FUNC! sorted rule list is:");
  2449. for (i = 0; i < count_rules; i++)
  2450. {
  2451. rules[i] = sorted_rules[i];
  2452. TRACE_VERB("%!FUNC! rule %d, vip: %ls, start port: %d", i, rules[i] . virtual_ip_addr, rules[i] . start_port);
  2453. }
  2454. /* invalidate the remaining rules in the buffer */
  2455. for (i = count_rules; i < *num_rules; i++)
  2456. rules [i] . valid = FALSE;
  2457. if (*num_rules < reg_data -> i_num_rules)
  2458. {
  2459. *num_rules = reg_data -> i_num_rules;
  2460. TRACE_INFO("<-%!FUNC! returning incomplete list of valid rules. Input buffer length too small.");
  2461. TRACE_VERB("<-%!FUNC! return %d", WLBS_TRUNCATED);
  2462. return WLBS_TRUNCATED;
  2463. }
  2464. *num_rules = reg_data -> i_num_rules;
  2465. TRACE_VERB("<-%!FUNC! return %d", WLBS_OK);
  2466. return WLBS_OK;
  2467. } /* end WlbsEnumPortRules */
  2468. EXTERN_C DWORD WINAPI WlbsGetPortRule
  2469. (
  2470. const PWLBS_REG_PARAMS reg_data,
  2471. DWORD vip,
  2472. DWORD pos,
  2473. OUT PWLBS_PORT_RULE rule
  2474. )
  2475. {
  2476. TRACE_VERB("->%!FUNC! vip 0x%lx, port %d", vip, pos);
  2477. int i;
  2478. if ((reg_data == NULL) || (rule == NULL))
  2479. {
  2480. TRACE_CRIT("%!FUNC! bad input parameter for registry data or output buffer");
  2481. TRACE_VERB("<-%!FUNC! return %d", WLBS_BAD_PARAMS);
  2482. return WLBS_BAD_PARAMS;
  2483. }
  2484. /* need to check whether pos is within the correct range */
  2485. if ( /* CLEAN_64BIT (pos < CVY_MIN_PORT) || */ (pos > CVY_MAX_PORT))
  2486. {
  2487. TRACE_CRIT("%!FUNC! bad input parameter for port number");
  2488. TRACE_VERB("<-%!FUNC! return %d", WLBS_BAD_PARAMS);
  2489. return WLBS_BAD_PARAMS;
  2490. }
  2491. /* search through the array for the rules */
  2492. for (i = 0; i < WLBS_MAX_RULES; i++)
  2493. {
  2494. /* check only the valid rules */
  2495. if (reg_data -> i_port_rules[i] . valid == TRUE)
  2496. {
  2497. /* check the range of the rule to see if pos fits into it */
  2498. if ((vip == IpAddressFromAbcdWsz(reg_data -> i_port_rules[i] . virtual_ip_addr)) &&
  2499. (pos >= reg_data -> i_port_rules[i] . start_port) &&
  2500. (pos <= reg_data -> i_port_rules[i] . end_port))
  2501. {
  2502. *rule = reg_data -> i_port_rules [i];
  2503. TRACE_INFO("%!FUNC! port rule found");
  2504. TRACE_VERB("<-%!FUNC! return %d", WLBS_OK);
  2505. return WLBS_OK;
  2506. }
  2507. }
  2508. }
  2509. /* no rule was found for this port */
  2510. TRACE_VERB("<-%!FUNC! return %d", WLBS_OK);
  2511. return WLBS_NOT_FOUND;
  2512. } /* end WlbsGetPortRule */
  2513. EXTERN_C DWORD WINAPI WlbsAddPortRule
  2514. (
  2515. PWLBS_REG_PARAMS reg_data,
  2516. const PWLBS_PORT_RULE rule
  2517. )
  2518. {
  2519. TRACE_VERB("->%!FUNC!");
  2520. int i;
  2521. DWORD vip;
  2522. if ((reg_data == NULL) || (rule == NULL))
  2523. {
  2524. TRACE_CRIT("%!FUNC! bad input parameter for registry data or port rule");
  2525. TRACE_VERB("<-%!FUNC! return %d", WLBS_BAD_PARAMS);
  2526. return WLBS_BAD_PARAMS;
  2527. }
  2528. /* Check if there is space for the new rule */
  2529. if (reg_data -> i_num_rules == WLBS_MAX_RULES)
  2530. {
  2531. TRACE_CRIT("%!FUNC! the maxiumum number of port rules %d are already defined", WLBS_MAX_RULES);
  2532. TRACE_VERB("<-%!FUNC! return %d", WLBS_MAX_PORT_RULES);
  2533. return WLBS_MAX_PORT_RULES;
  2534. }
  2535. /* check the rule for valid values */
  2536. /* check for non-zero vip and conflict with dip */
  2537. vip = IpAddressFromAbcdWsz(rule -> virtual_ip_addr);
  2538. if (vip == 0 || (INADDR_NONE == vip && lstrcmpi(rule -> virtual_ip_addr, CVY_DEF_ALL_VIP) != 0))
  2539. {
  2540. TRACE_CRIT("%!FUNC! vip %ls in port rule is malformed", rule -> virtual_ip_addr);
  2541. TRACE_VERB("<-%!FUNC! return %d", WLBS_BAD_PORT_PARAMS);
  2542. return WLBS_BAD_PORT_PARAMS;
  2543. }
  2544. if (vip == IpAddressFromAbcdWsz(reg_data->ded_ip_addr))
  2545. {
  2546. TRACE_CRIT("%!FUNC! vip %ls in port rule is in used as a dedicated IP address", rule -> virtual_ip_addr);
  2547. TRACE_VERB("<-%!FUNC! return %d", WLBS_BAD_PORT_PARAMS);
  2548. return WLBS_BAD_PORT_PARAMS;
  2549. }
  2550. /* first check the range of the start and end ports */
  2551. if ((rule -> start_port > rule -> end_port) ||
  2552. // CLEAN_64BIT (rule -> start_port < CVY_MIN_PORT) ||
  2553. (rule -> end_port > CVY_MAX_PORT))
  2554. {
  2555. TRACE_CRIT
  2556. (
  2557. "%!FUNC! port range of rule is invalid; start port = %d, end port = %d, max allowed port = %d",
  2558. rule -> start_port,
  2559. rule -> end_port,
  2560. CVY_MAX_PORT
  2561. );
  2562. TRACE_VERB("<-%!FUNC! return %d", WLBS_BAD_PORT_PARAMS);
  2563. return WLBS_BAD_PORT_PARAMS;
  2564. }
  2565. /* check the protocol range */
  2566. if ((rule -> protocol < CVY_MIN_PROTOCOL) || (rule -> protocol > CVY_MAX_PROTOCOL))
  2567. {
  2568. TRACE_CRIT("%!FUNC! invalid protocol code specified %d", rule -> protocol);
  2569. TRACE_VERB("<-%!FUNC! return %d", WLBS_BAD_PORT_PARAMS);
  2570. return WLBS_BAD_PORT_PARAMS;
  2571. }
  2572. /* check filtering mode to see whether it is within range */
  2573. if ((rule -> mode < CVY_MIN_MODE) || (rule -> mode > CVY_MAX_MODE))
  2574. {
  2575. TRACE_CRIT("%!FUNC! invalid filtering mode specified %d", rule -> mode);
  2576. TRACE_VERB("<-%!FUNC! return %d", WLBS_BAD_PORT_PARAMS);
  2577. return WLBS_BAD_PORT_PARAMS;
  2578. }
  2579. /* check load weight and affinity if multiple hosts */
  2580. if (rule -> mode == CVY_MULTI)
  2581. {
  2582. if ((rule -> mode_data . multi . affinity < CVY_MIN_AFFINITY) ||
  2583. (rule -> mode_data . multi . affinity > CVY_MAX_AFFINITY))
  2584. {
  2585. TRACE_CRIT("%!FUNC! invalid affinity code specified %d", rule -> mode_data . multi . affinity);
  2586. TRACE_VERB("<-%!FUNC! return %d", WLBS_BAD_PORT_PARAMS);
  2587. return WLBS_BAD_PORT_PARAMS;
  2588. }
  2589. if ((rule -> mode_data . multi . equal_load < CVY_MIN_EQUAL_LOAD) ||
  2590. (rule -> mode_data . multi . equal_load > CVY_MAX_EQUAL_LOAD))
  2591. {
  2592. TRACE_CRIT("%!FUNC! invalid equal load percentage specified %d", rule -> mode_data . multi . equal_load);
  2593. TRACE_VERB("<-%!FUNC! return %d", WLBS_BAD_PORT_PARAMS);
  2594. return WLBS_BAD_PORT_PARAMS;
  2595. }
  2596. if (! rule -> mode_data . multi . equal_load)
  2597. {
  2598. if ((rule -> mode_data . multi . load > CVY_MAX_LOAD))
  2599. //CLEAN_64BIT (rule -> mode_data . multi . load < CVY_MIN_LOAD) ||
  2600. {
  2601. TRACE_CRIT("%!FUNC! invalid non-equal load percentage specified %d", rule -> mode_data . multi . load);
  2602. TRACE_VERB("<-%!FUNC! return %d", WLBS_BAD_PORT_PARAMS);
  2603. return WLBS_BAD_PORT_PARAMS;
  2604. }
  2605. }
  2606. }
  2607. /* check handling priority range if single host */
  2608. if (rule -> mode == CVY_SINGLE)
  2609. {
  2610. if ((rule -> mode_data . single . priority < CVY_MIN_PRIORITY) ||
  2611. (rule -> mode_data . single . priority > CVY_MAX_PRIORITY))
  2612. {
  2613. TRACE_CRIT("%!FUNC! invalid handlind priority specified %d", rule -> mode_data . single . priority);
  2614. TRACE_VERB("<-%!FUNC! return %d", WLBS_BAD_PORT_PARAMS);
  2615. return WLBS_BAD_PORT_PARAMS;
  2616. }
  2617. }
  2618. /* go through the rule list and then check for overlapping conditions */
  2619. for (i = 0; i < WLBS_MAX_RULES; i++)
  2620. {
  2621. if (reg_data -> i_port_rules[i] . valid == TRUE)
  2622. {
  2623. if ((IpAddressFromAbcdWsz(reg_data -> i_port_rules[i] . virtual_ip_addr) == vip)
  2624. && (( (reg_data -> i_port_rules[i] . start_port <= rule -> start_port) &&
  2625. (reg_data -> i_port_rules[i] . end_port >= rule -> start_port)) ||
  2626. ( (reg_data -> i_port_rules[i] . start_port >= rule -> start_port) &&
  2627. (reg_data -> i_port_rules[i] . start_port <= rule -> end_port))))
  2628. {
  2629. TRACE_CRIT
  2630. (
  2631. "%!FUNC! port range for new rule overlaps an existing rule; vip = %ls, start port = %d, end port = %d, existing rule: start port = %d, end port = %d",
  2632. rule -> virtual_ip_addr,
  2633. rule -> start_port,
  2634. rule -> end_port,
  2635. reg_data -> i_port_rules[i] . start_port,
  2636. reg_data -> i_port_rules[i] . end_port
  2637. );
  2638. TRACE_VERB("<-%!FUNC! return %d", WLBS_PORT_OVERLAP);
  2639. return WLBS_PORT_OVERLAP;
  2640. }
  2641. }
  2642. }
  2643. /* go through the rule list and find out the first empty spot
  2644. and write out the port rule */
  2645. for (i = 0 ; i < WLBS_MAX_RULES ; i++)
  2646. {
  2647. if (reg_data -> i_port_rules[i] . valid == FALSE)
  2648. {
  2649. reg_data -> i_num_rules ++ ;
  2650. reg_data -> i_port_rules [i] = *rule;
  2651. reg_data -> i_port_rules [i] . valid = TRUE;
  2652. CVY_RULE_CODE_SET(& reg_data -> i_port_rules [i]);
  2653. TRACE_INFO
  2654. (
  2655. "%!FUNC! port rule added for vip = %ls, start port = %d, end port = %d",
  2656. rule -> virtual_ip_addr,
  2657. rule -> start_port,
  2658. rule -> end_port
  2659. );
  2660. TRACE_VERB("<-%!FUNC! return %d", WLBS_OK);
  2661. return WLBS_OK;
  2662. }
  2663. }
  2664. TRACE_CRIT
  2665. (
  2666. "%!FUNC! data integrity error. No room for rule, but problem should have been caught earlier. vip = %ls, start port = %d, end port = %d",
  2667. rule -> virtual_ip_addr,
  2668. rule -> start_port,
  2669. rule -> end_port
  2670. );
  2671. TRACE_VERB("<-%!FUNC! return %d", WLBS_MAX_PORT_RULES);
  2672. return WLBS_MAX_PORT_RULES;
  2673. } /* end WlbsAddPortRule */
  2674. EXTERN_C DWORD WINAPI WlbsDeletePortRule
  2675. (
  2676. PWLBS_REG_PARAMS reg_data,
  2677. DWORD vip,
  2678. DWORD port
  2679. )
  2680. {
  2681. TRACE_VERB("->%!FUNC! vip = 0x%lx, %d", vip, port);
  2682. int i;
  2683. if (reg_data == NULL)
  2684. {
  2685. TRACE_CRIT("%!FUNC! registry data not provided");
  2686. TRACE_VERB("<-%!FUNC! return %d", WLBS_BAD_PARAMS);
  2687. return WLBS_BAD_PARAMS;
  2688. }
  2689. /* check if the port is within the correct range */
  2690. if ( /* CLEAN_64BIT (port < CVY_MIN_PORT) ||*/ (port > CVY_MAX_PORT))
  2691. {
  2692. TRACE_CRIT("%!FUNC! specified port %d is out of range", port);
  2693. TRACE_VERB("<-%!FUNC! return %d", WLBS_BAD_PARAMS);
  2694. return WLBS_BAD_PARAMS;
  2695. }
  2696. /* find the rule associated with this port */
  2697. for (i = 0; i < WLBS_MAX_RULES; i++)
  2698. {
  2699. if (reg_data -> i_port_rules[i] . valid)
  2700. {
  2701. if ((vip == IpAddressFromAbcdWsz(reg_data -> i_port_rules[i] . virtual_ip_addr)) &&
  2702. (port >= reg_data -> i_port_rules[i] . start_port) &&
  2703. (port <= reg_data -> i_port_rules[i] . end_port))
  2704. {
  2705. reg_data -> i_port_rules[i] . valid = FALSE;
  2706. reg_data -> i_num_rules -- ;
  2707. TRACE_INFO
  2708. (
  2709. "%!FUNC! deleted port rule for port %d. Rule was vip = %ls, start port = %d, end port = %d",
  2710. port,
  2711. reg_data -> i_port_rules[i] . virtual_ip_addr,
  2712. reg_data -> i_port_rules[i] . start_port,
  2713. reg_data -> i_port_rules[i] . end_port
  2714. );
  2715. TRACE_VERB("<-%!FUNC! return %d", WLBS_OK);
  2716. return WLBS_OK;
  2717. }
  2718. }
  2719. }
  2720. TRACE_INFO("<-%!FUNC! port rule for port %d not found", port);
  2721. TRACE_VERB("<-%!FUNC! return %d", WLBS_NOT_FOUND);
  2722. return WLBS_NOT_FOUND;
  2723. } /* end WlbsDeletePortRule */
  2724. EXTERN_C VOID WINAPI WlbsDeleteAllPortRules
  2725. (
  2726. PWLBS_REG_PARAMS reg_data
  2727. )
  2728. {
  2729. TRACE_VERB("->%!FUNC!");
  2730. reg_data -> i_num_rules = 0;
  2731. ZeroMemory(reg_data -> i_port_rules, sizeof(reg_data -> i_port_rules));
  2732. TRACE_VERB("<-%!FUNC!");
  2733. } /* end WlbsDeleteAllPortRules */
  2734. EXTERN_C DWORD WINAPI WlbsSetRemotePassword
  2735. (
  2736. PWLBS_REG_PARAMS reg_data,
  2737. const WCHAR* password
  2738. )
  2739. {
  2740. if (reg_data == NULL)
  2741. return WLBS_BAD_PARAMS;
  2742. if (password != NULL)
  2743. {
  2744. reg_data -> i_rct_password = License_wstring_encode ((WCHAR*)password);
  2745. }
  2746. else
  2747. reg_data -> i_rct_password = CVY_DEF_RCT_PASSWORD;
  2748. return WLBS_OK;
  2749. } /* end WlbsSetRemotePassword */
  2750. //+----------------------------------------------------------------------------
  2751. //
  2752. // Function: RegChangeNetworkAddress
  2753. //
  2754. // Description: Change the mac address of the adapter in registry
  2755. //
  2756. // Arguments: const GUID& AdapterGuid - the adapter guid to look up settings
  2757. // TCHAR mac_address -
  2758. // BOOL fRemove - true to remove address, false to write address
  2759. //
  2760. // Returns: bool - true if succeeded
  2761. //
  2762. // History: fengsun Created Header 1/18/00
  2763. //
  2764. //+----------------------------------------------------------------------------
  2765. bool WINAPI RegChangeNetworkAddress(const GUID& AdapterGuid, const WCHAR* mac_address, BOOL fRemove)
  2766. {
  2767. if (NULL != mac_address)
  2768. TRACE_VERB("->%!FUNC! mac = %ls", mac_address);
  2769. else
  2770. TRACE_VERB("->%!FUNC! mac = NULL");
  2771. HKEY key = NULL;
  2772. LONG status;
  2773. DWORD size;
  2774. DWORD type;
  2775. TCHAR net_addr [CVY_MAX_NETWORK_ADDR + 1];
  2776. HDEVINFO hdi = NULL;
  2777. SP_DEVINFO_DATA deid;
  2778. if (fRemove)
  2779. {
  2780. TRACE_INFO("%!FUNC! remove mac address");
  2781. }
  2782. else
  2783. {
  2784. status = CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, mac_address, -1, CVY_DEF_UNICAST_NETWORK_ADDR, -1);
  2785. if (status == 0)
  2786. {
  2787. TRACE_CRIT("MAC address compare with the default value failed with error 0x%x", GetLastError());
  2788. fRemove = TRUE;
  2789. }
  2790. else if (status == CSTR_EQUAL)
  2791. {
  2792. // The MAC is not set as expected
  2793. TRACE_CRIT("%!FUNC! failed to set mac address to %ls because this is the default address (no VIP was specified)", mac_address);
  2794. fRemove = TRUE;
  2795. }
  2796. else
  2797. {
  2798. // Things look good
  2799. TRACE_INFO("%!FUNC! to %ws", mac_address);
  2800. }
  2801. }
  2802. /*
  2803. - write NetworkAddress value into the cluster adapter's params key
  2804. if mac address changed, or remove it if switched to multicast mode
  2805. */
  2806. key = RegOpenWlbsSetting(AdapterGuid, true);
  2807. if (key == NULL)
  2808. {
  2809. TRACE_CRIT("%!FUNC! failed to open registry for the specified adapter");
  2810. goto error;
  2811. }
  2812. TCHAR driver_name[CVY_STR_SIZE]; // the NIC card name for the cluster
  2813. size = sizeof (driver_name);
  2814. status = RegQueryValueEx (key, CVY_NAME_CLUSTER_NIC, 0L, & type, (LPBYTE) driver_name,
  2815. & size);
  2816. if (status != ERROR_SUCCESS)
  2817. {
  2818. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d", CVY_NAME_CLUSTER_NIC, status);
  2819. goto error;
  2820. }
  2821. status = RegCloseKey(key);
  2822. if (ERROR_SUCCESS != status)
  2823. {
  2824. TRACE_CRIT("%!FUNC! registry close failed with %d", status);
  2825. // Do not goto error. Added this check as part of implementing tracing
  2826. }
  2827. key = NULL;
  2828. hdi = SetupDiCreateDeviceInfoList (&GUID_DEVCLASS_NET, NULL);
  2829. if (hdi == INVALID_HANDLE_VALUE)
  2830. {
  2831. TRACE_CRIT("%!FUNC! SetupDiCreateDeviceInfoList failed");
  2832. goto error;
  2833. }
  2834. ZeroMemory(&deid, sizeof(deid));
  2835. deid.cbSize = sizeof(deid);
  2836. if (! SetupDiOpenDeviceInfo (hdi, driver_name, NULL, 0, &deid))
  2837. {
  2838. TRACE_CRIT("%!FUNC! SetupDiOpenDeviceInfo failed");
  2839. goto error;
  2840. }
  2841. key = SetupDiOpenDevRegKey (hdi, &deid, DICS_FLAG_GLOBAL, 0,
  2842. DIREG_DRV, KEY_ALL_ACCESS);
  2843. if (key == INVALID_HANDLE_VALUE)
  2844. {
  2845. TRACE_CRIT("%!FUNC! SetupDiOpenDevRegKey failed");
  2846. goto error;
  2847. }
  2848. /* Now the key has been obtained and this can be passed to the RegChangeNetworkAddress call */
  2849. if ((/*global_info.mac_addr_change ||*/ !fRemove)) /* a write is required */
  2850. {
  2851. /* Check if the saved name exists.
  2852. * If it does not, create a new field and save the old address.
  2853. * Write the new address and return
  2854. */
  2855. size = sizeof (TCHAR) * CVY_STR_SIZE;
  2856. status = RegQueryValueEx (key, CVY_NAME_SAVED_NET_ADDR, 0L, &type,
  2857. (LPBYTE) net_addr, &size);
  2858. if (status != ERROR_SUCCESS) /* there is no saved address. so create a field */
  2859. {
  2860. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d", CVY_NAME_SAVED_NET_ADDR, status);
  2861. /* Query the existing mac address in order to save it */
  2862. size = sizeof (net_addr);
  2863. status = RegQueryValueEx (key, CVY_NAME_NET_ADDR, 0L, &type,
  2864. (LPBYTE) net_addr, &size);
  2865. if (status != ERROR_SUCCESS) /* create an empty saved address */
  2866. {
  2867. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d", CVY_NAME_NET_ADDR, status);
  2868. net_addr [0] = 0;
  2869. size = 0;
  2870. }
  2871. status = RegSetValueEx (key, CVY_NAME_SAVED_NET_ADDR, 0L, CVY_TYPE_NET_ADDR,
  2872. (LPBYTE) net_addr, size);
  2873. /* Unable to save the old value */
  2874. if (status != ERROR_SUCCESS)
  2875. {
  2876. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_SAVED_NET_ADDR, status);
  2877. goto error;
  2878. }
  2879. }
  2880. /* Write the new network address */
  2881. size = _tcslen (mac_address) * sizeof (TCHAR);
  2882. status = RegSetValueEx (key, CVY_NAME_NET_ADDR, 0L, CVY_TYPE_NET_ADDR,
  2883. (LPBYTE)mac_address, size);
  2884. /* Unable to write the new address */
  2885. if (status != ERROR_SUCCESS)
  2886. {
  2887. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_NET_ADDR, status);
  2888. goto error;
  2889. }
  2890. }
  2891. else // remove the address
  2892. {
  2893. /* If the saved field exists,
  2894. * copy this address into the mac address
  2895. * and remove the saved field and return.
  2896. */
  2897. size = sizeof (net_addr);
  2898. status = RegQueryValueEx (key, CVY_NAME_SAVED_NET_ADDR, 0L, &type,
  2899. (LPBYTE)net_addr, &size);
  2900. if (status == ERROR_SUCCESS)
  2901. {
  2902. /* delete both fields if saved address is empty */
  2903. if ((size == 0) || (_tcsicmp (net_addr, _TEXT("none")) == 0))
  2904. {
  2905. status = RegDeleteValue (key, CVY_NAME_SAVED_NET_ADDR);
  2906. if (ERROR_SUCCESS != status)
  2907. {
  2908. TRACE_CRIT("%!FUNC! registry delete for %ls failed with %d", CVY_NAME_SAVED_NET_ADDR, status);
  2909. }
  2910. status = RegDeleteValue (key, CVY_NAME_NET_ADDR);
  2911. if (ERROR_SUCCESS != status)
  2912. {
  2913. TRACE_CRIT("%!FUNC! registry delete for %ls failed with %d", CVY_NAME_NET_ADDR, status);
  2914. }
  2915. }
  2916. else /* copy saved address as the network address and delete the saved address field */
  2917. {
  2918. status = RegDeleteValue (key, CVY_NAME_SAVED_NET_ADDR);
  2919. if (ERROR_SUCCESS != status)
  2920. {
  2921. TRACE_CRIT("%!FUNC! registry delete for %ls failed with %d", CVY_NAME_SAVED_NET_ADDR, status);
  2922. }
  2923. size = _tcslen (net_addr) * sizeof (TCHAR);
  2924. status = RegSetValueEx (key, CVY_NAME_NET_ADDR, 0L, CVY_TYPE_NET_ADDR,
  2925. (LPBYTE) net_addr, size);
  2926. /* Unable to set the original address */
  2927. if (status != ERROR_SUCCESS)
  2928. {
  2929. TRACE_CRIT("%!FUNC! registry write for %ls failed with %d", CVY_NAME_NET_ADDR, status);
  2930. goto error;
  2931. }
  2932. }
  2933. }
  2934. else
  2935. {
  2936. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d", CVY_NAME_SAVED_NET_ADDR, status);
  2937. }
  2938. }
  2939. status = RegCloseKey (key);
  2940. if (ERROR_SUCCESS != status)
  2941. {
  2942. TRACE_CRIT("%!FUNC! registry close failed");
  2943. }
  2944. key = NULL;
  2945. TRACE_VERB("<-%!FUNC! return true");
  2946. return true;
  2947. error:
  2948. if (key != NULL)
  2949. {
  2950. status = RegCloseKey(key);
  2951. if (ERROR_SUCCESS != status)
  2952. {
  2953. TRACE_CRIT("%!FUNC! registry close failed in error recovery code");
  2954. }
  2955. }
  2956. if (hdi != NULL)
  2957. SetupDiDestroyDeviceInfoList (hdi);
  2958. TRACE_VERB("<-%!FUNC! return false");
  2959. return false;
  2960. }
  2961. //+----------------------------------------------------------------------------
  2962. //
  2963. // Function: NotifyAdapterAddressChange
  2964. //
  2965. // Description: Notify the adapter to reload MAC address
  2966. // The parameter is different from NotifyAdapterAddressChange.
  2967. // Can not overload, because the function has to be exported
  2968. //
  2969. // Arguments: const WCHAR* driver_name -
  2970. //
  2971. // Returns: void WINAPI -
  2972. //
  2973. // History: fengsun Created 5/20/00
  2974. //
  2975. //+----------------------------------------------------------------------------
  2976. void WINAPI NotifyAdapterAddressChange (const WCHAR * driver_name) {
  2977. NotifyAdapterPropertyChange(driver_name, DICS_PROPCHANGE);
  2978. }
  2979. //+----------------------------------------------------------------------------
  2980. //
  2981. // Function: NotifyAdapterAddressChangeEx
  2982. //
  2983. // Description: Notify the adapter to reload MAC address
  2984. // The parameter is different from NotifyAdapterAddressChange.
  2985. // Can not overload, because the function has to be exported
  2986. //
  2987. // Arguments: const WCHAR* driver_name -
  2988. // const GUID& AdapterGuid
  2989. // bool bWaitAndQuery
  2990. //
  2991. // Returns: void WINAPI -
  2992. //
  2993. // History: fengsun Created 5/20/00
  2994. // karthicn Edited 5/29/02 - Added the wait to "query" NLB to ensure that
  2995. // the binding process is complete before we
  2996. // return.
  2997. //
  2998. //+----------------------------------------------------------------------------
  2999. void WINAPI NotifyAdapterAddressChangeEx (const WCHAR * driver_name, const GUID& AdapterGuid, bool bWaitAndQuery) {
  3000. TRACE_INFO("->%!FUNC! bWaitAndQuery = %ls", bWaitAndQuery ? L"TRUE" : L"FALSE");
  3001. NotifyAdapterPropertyChange(driver_name, DICS_PROPCHANGE);
  3002. /*
  3003. In order for the network adapter to pick up the new mac address from the registry, it has
  3004. to be disabled and re-enabled. During the disable, NLB and Tcp/Ip are Unbound from the
  3005. network adapter and NLB respectively. During the re-enable, NLB and Tcp/ip are bound to
  3006. the network adapter and NLB respectively. Because the function NotifyAdapterPropertyChange (called above)
  3007. performs the disable and re-enable operation asynchronously, it returns BEFORE the operation
  3008. is completed. The following block of code aims to wait until the operation is completed. We
  3009. check for the completeness of the operation by querying the NLB driver. We are relying on
  3010. the fact that the NLB driver does NOT reply to a Query when the binding process is ongoing.
  3011. This wait is necessary due to the following reasons:
  3012. 1. Prompt for reboot when mac address change + ip address change from netconfig:
  3013. Say, a NLB parameter (like cluster ip) change that causes a mac address change is done from
  3014. Netconfig. In the same session, let us say that a ip address is changed in tcp/ip.
  3015. If this wait was not there, we will return prematurely from this function and hence, from
  3016. "ApplyPnPChanges" function in our notify object. This causes tcp/ip notify object's
  3017. "ApplyPnPChanges" function to be called. Tcp/ip's "ApplyPnPChanges" attempts to make
  3018. the ip address change, but finds that Tcp/ip is NOT yet bound to the network adapter (the
  3019. binding process is not completed yet). Though it is able to add the ip address eventually,
  3020. it freaks out and pops up the prompt for reboot.
  3021. 2. ParamCommitChanges returns prematurely: If this wait was not there, "ParamCommitChanges" which
  3022. calls this function will return prematurely. The wmi provider (called by App. Center) and
  3023. NLB Manager provider call "ParamCommitChanges" and want the assurance that the process is
  3024. complete when the function returns.
  3025. -- KarthicN, 05-29-02
  3026. */
  3027. if (bWaitAndQuery == true)
  3028. {
  3029. //
  3030. // Max wait time = dwWaitBeforeInitial + (dwMaxNumOfRetries * dwWaitBeforeRetry)
  3031. // Max attempts = 1 + dwMaxNumOfRetries
  3032. //
  3033. //
  3034. // Min wait time = dwWaitBeforeInitial
  3035. // Min attempts = 1
  3036. //
  3037. DWORD dwWaitBeforeInitial = 2000;
  3038. DWORD dwWaitBeforeRetry = 3000;
  3039. DWORD dwMaxNumOfRetries = 4;
  3040. DWORD dwIdx = 0;
  3041. HANDLE hTempDeviceWlbs;
  3042. TRACE_INFO("%!FUNC! Sleeping (BEFORE attempt #1) for %d ms, Total Wait (including current) : %d ms, Max Wait: %d ms",
  3043. dwWaitBeforeInitial, dwWaitBeforeInitial, dwWaitBeforeInitial + (dwMaxNumOfRetries * dwWaitBeforeRetry));
  3044. Sleep(dwWaitBeforeInitial);
  3045. while(true)
  3046. {
  3047. TRACE_INFO("%!FUNC! Calling (attempt #%d) CreateFile() to NLB driver", dwIdx+1);
  3048. hTempDeviceWlbs = CreateFile(_TEXT("\\\\.\\WLBS"), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
  3049. if (hTempDeviceWlbs != INVALID_HANDLE_VALUE)
  3050. {
  3051. IOCTL_CVY_BUF in_buf;
  3052. IOCTL_CVY_BUF out_buf;
  3053. // Send a "Query" IOCTL to the NLB driver
  3054. DWORD dwRet = WlbsLocalControl (hTempDeviceWlbs, AdapterGuid, IOCTL_CVY_QUERY, & in_buf, & out_buf, NULL);
  3055. CloseHandle(hTempDeviceWlbs);
  3056. if (dwRet != WLBS_IO_ERROR)
  3057. {
  3058. TRACE_INFO("%!FUNC! Query (attempt #%d) to NLB driver SUCCEEDS, Breaking out... !!!", dwIdx+1);
  3059. break; // Break out of the while(true)
  3060. }
  3061. TRACE_INFO("%!FUNC! Query (attempt #%d) to NLB driver FAILS !!!", dwIdx+1);
  3062. }
  3063. else // CreateFile() returned INVALID_HANDLE_VALUE
  3064. {
  3065. DWORD dwStatus = GetLastError();
  3066. TRACE_INFO("%!FUNC! CreateFile() failed opening (attempt #%d) \\\\.\\WLBS device. Error is %d", dwIdx+1, dwStatus);
  3067. }
  3068. if (dwIdx++ >= dwMaxNumOfRetries)
  3069. {
  3070. TRACE_CRIT("%!FUNC! Exhausted the Max wait time (%d ms) and Query is still NOT successful. Giving up...",
  3071. dwWaitBeforeInitial + (dwMaxNumOfRetries * dwWaitBeforeRetry));
  3072. break;
  3073. }
  3074. TRACE_INFO("%!FUNC! Sleeping (BEFORE attempt #%d) for %d ms, Total Wait (including current) : %d ms, Max Wait: %d ms",
  3075. dwIdx+1, dwWaitBeforeRetry, dwWaitBeforeInitial + (dwIdx * dwWaitBeforeRetry),
  3076. dwWaitBeforeInitial + (dwMaxNumOfRetries * dwWaitBeforeRetry));
  3077. Sleep(dwWaitBeforeRetry);
  3078. }
  3079. }
  3080. TRACE_INFO("<-%!FUNC!");
  3081. }
  3082. /*
  3083. * Function: NotifyAdapterPropertyChange
  3084. * Description: Notify a device that a property change event has occurred.
  3085. * Event should be one of: DICS_PROPCHANGE, DICS_DISABLE, DICS_ENABLE
  3086. * Author: shouse 7.17.00
  3087. */
  3088. void WINAPI NotifyAdapterPropertyChange (const WCHAR * driver_name, DWORD eventFlag) {
  3089. if (NULL == driver_name)
  3090. {
  3091. TRACE_VERB("->%!FUNC! NULL driver name, event flag %d", eventFlag);
  3092. }
  3093. else
  3094. {
  3095. TRACE_VERB("->%!FUNC! driver %ls, event flag %d", driver_name, eventFlag);
  3096. }
  3097. HDEVINFO hdi = NULL;
  3098. SP_DEVINFO_DATA deid;
  3099. hdi = SetupDiCreateDeviceInfoList (&GUID_DEVCLASS_NET, NULL);
  3100. if (hdi == INVALID_HANDLE_VALUE)
  3101. {
  3102. TRACE_CRIT("%!FUNC! SetupDiCreateDeviceInfoList failed");
  3103. goto end;
  3104. }
  3105. ZeroMemory(&deid, sizeof(deid));
  3106. deid.cbSize = sizeof(deid);
  3107. if (! SetupDiOpenDeviceInfo (hdi, driver_name, NULL, 0, &deid))
  3108. {
  3109. TRACE_CRIT("%!FUNC! SetupDiOpenDeviceInfo failed");
  3110. goto end;
  3111. }
  3112. SP_PROPCHANGE_PARAMS pcp;
  3113. SP_DEVINSTALL_PARAMS deip;
  3114. ZeroMemory(&pcp, sizeof(pcp));
  3115. pcp.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
  3116. pcp.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
  3117. pcp.StateChange = eventFlag;
  3118. pcp.Scope = DICS_FLAG_GLOBAL;
  3119. pcp.HwProfile = 0;
  3120. // Now we set the structure as the device info data's
  3121. // class install params
  3122. if (! SetupDiSetClassInstallParams(hdi, &deid,
  3123. (PSP_CLASSINSTALL_HEADER)(&pcp),
  3124. sizeof(pcp)))
  3125. {
  3126. TRACE_CRIT("%!FUNC! SetupDiSetClassInstallParams failed");
  3127. goto end;
  3128. }
  3129. // Now we need to set the "we have a class install params" flag
  3130. // in the device install params
  3131. // initialize out parameter and set its cbSize field
  3132. ZeroMemory(&deip, sizeof(SP_DEVINSTALL_PARAMS));
  3133. deip.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  3134. // get the header
  3135. if (! SetupDiGetDeviceInstallParams(hdi, &deid, &deip))
  3136. {
  3137. TRACE_CRIT("%!FUNC! SetupDiGetDeviceInstallParams failed");
  3138. goto end;
  3139. }
  3140. deip.Flags |= DI_CLASSINSTALLPARAMS;
  3141. if (! SetupDiSetDeviceInstallParams(hdi, &deid, &deip))
  3142. {
  3143. TRACE_CRIT("%!FUNC! SetupDiSetDeviceInstallParams failed");
  3144. goto end;
  3145. }
  3146. // Notify the driver that the state has changed
  3147. if (! SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, hdi, &deid))
  3148. {
  3149. TRACE_CRIT("%!FUNC! SetupDiCallClassInstaller failed");
  3150. goto end;
  3151. }
  3152. // Set the properties change flag in the device info to
  3153. // let anyone who cares know that their ui might need
  3154. // updating to reflect any change in the device's status
  3155. // We can't let any failures here stop us so we ignore
  3156. // return values
  3157. SetupDiGetDeviceInstallParams(hdi, &deid, &deip);
  3158. deip.Flags |= DI_PROPERTIES_CHANGE;
  3159. SetupDiSetDeviceInstallParams(hdi, &deid, &deip);
  3160. end:
  3161. if (hdi != NULL)
  3162. SetupDiDestroyDeviceInfoList (hdi);
  3163. TRACE_VERB("<-%!FUNC!");
  3164. }
  3165. /*
  3166. * Function: GetDeviceNameFromGUID
  3167. * Description: Given a GUID, return the driver name.
  3168. * Author: shouse 7.17.00
  3169. */
  3170. void WINAPI GetDriverNameFromGUID (const GUID & AdapterGuid, OUT WCHAR * driver_name, DWORD size) {
  3171. if (NULL == driver_name)
  3172. {
  3173. TRACE_VERB("->%!FUNC! NULL driver name");
  3174. }
  3175. else
  3176. {
  3177. TRACE_VERB("->%!FUNC! driver %ls", driver_name);
  3178. }
  3179. HKEY key = NULL;
  3180. DWORD type;
  3181. DWORD dwStatus = 0;
  3182. if (!(key = RegOpenWlbsSetting(AdapterGuid, true)))
  3183. {
  3184. TRACE_CRIT("%!FUNC! failed opening nlb registry settings");
  3185. TRACE_VERB("<-%!FUNC! on error");
  3186. return;
  3187. }
  3188. dwStatus = RegQueryValueEx(key, CVY_NAME_CLUSTER_NIC, 0L, &type, (LPBYTE)driver_name, &size);
  3189. if (ERROR_SUCCESS != dwStatus)
  3190. {
  3191. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d", CVY_NAME_CLUSTER_NIC, dwStatus);
  3192. // This code was added for tracing. There was not abort before so don't abort now.
  3193. }
  3194. dwStatus = RegCloseKey(key);
  3195. if (ERROR_SUCCESS != dwStatus)
  3196. {
  3197. TRACE_CRIT("%!FUNC! registry close failed with %d", dwStatus);
  3198. // This code was added for tracing. There was not abort before so don't abort now.
  3199. }
  3200. TRACE_VERB("<-%!FUNC! on error");
  3201. }
  3202. //+----------------------------------------------------------------------------
  3203. //
  3204. // Function: RegReadAdapterIp
  3205. //
  3206. // Description: Read the adapter IP settings
  3207. //
  3208. // Arguments: const GUID& AdapterGuid -
  3209. // OUT DWORD& dwClusterIp -
  3210. // OUT DWORD& dwDedicatedIp -
  3211. //
  3212. // Returns: bool -
  3213. //
  3214. // History: fengsun Created Header 3/9/00
  3215. //
  3216. //+----------------------------------------------------------------------------
  3217. bool WINAPI RegReadAdapterIp(const GUID& AdapterGuid,
  3218. OUT DWORD& dwClusterIp, OUT DWORD& dwDedicatedIp)
  3219. {
  3220. TRACE_VERB("->%!FUNC!");
  3221. HKEY key;
  3222. LONG status;
  3223. DWORD size;
  3224. key = RegOpenWlbsSetting(AdapterGuid, true);
  3225. if (key == NULL)
  3226. {
  3227. TRACE_CRIT("%!FUNC! failed to read nlb settings from registry");
  3228. TRACE_VERB("<-%!FUNC! return false");
  3229. return false;
  3230. }
  3231. bool local = false;
  3232. TCHAR nic_name[CVY_STR_SIZE]; // Virtual NIC name
  3233. size = sizeof (nic_name);
  3234. status = RegQueryValueEx (key, CVY_NAME_VIRTUAL_NIC, 0L, NULL,
  3235. (LPBYTE) nic_name, & size);
  3236. if (status == ERROR_SUCCESS)
  3237. {
  3238. TCHAR szIpAddress[CVY_STR_SIZE];
  3239. size = sizeof (TCHAR) * CVY_STR_SIZE;
  3240. status = RegQueryValueEx (key, CVY_NAME_CL_IP_ADDR, 0L, NULL,
  3241. (LPBYTE) szIpAddress, & size);
  3242. if (status == ERROR_SUCCESS)
  3243. {
  3244. dwClusterIp = IpAddressFromAbcdWsz (szIpAddress);
  3245. local = true;
  3246. }
  3247. else
  3248. {
  3249. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d", CVY_NAME_CL_IP_ADDR, status);
  3250. }
  3251. status = RegQueryValueEx (key, CVY_NAME_DED_IP_ADDR, 0L, NULL,
  3252. (LPBYTE) szIpAddress, & size);
  3253. if (status == ERROR_SUCCESS)
  3254. {
  3255. dwDedicatedIp = IpAddressFromAbcdWsz (szIpAddress);
  3256. }
  3257. else
  3258. {
  3259. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d", CVY_NAME_DED_IP_ADDR, status);
  3260. }
  3261. }
  3262. else
  3263. {
  3264. TRACE_CRIT("%!FUNC! registry read for %ls failed with %d", CVY_NAME_VIRTUAL_NIC, status);
  3265. }
  3266. status = RegCloseKey (key);
  3267. if (ERROR_SUCCESS != status)
  3268. {
  3269. TRACE_CRIT("%!FUNC! registry close failed with %d", status);
  3270. }
  3271. TRACE_VERB("<-%!FUNC! on error");
  3272. return local;
  3273. }