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

984 lines
31 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1996-2000 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // IpAddr.cpp
  7. //
  8. // Abstract:
  9. // Implementation of the CIpAddrParamsPage class.
  10. //
  11. // Author:
  12. // David Potter (davidp) June 5, 1996
  13. //
  14. // Revision History:
  15. //
  16. // Notes:
  17. //
  18. /////////////////////////////////////////////////////////////////////////////
  19. #include "stdafx.h"
  20. #include <clusapi.h>
  21. #include <clusudef.h>
  22. #include "CluAdmX.h"
  23. #include "ExtObj.h"
  24. #include "IpAddr.h"
  25. #include "DDxDDv.h"
  26. #include "HelpData.h"
  27. #include "PropList.h"
  28. #include "AdmNetUtils.h" // for BIsValidxxx net utility functions
  29. #ifdef _DEBUG
  30. #define new DEBUG_NEW
  31. #undef THIS_FILE
  32. static char THIS_FILE[] = __FILE__;
  33. #endif
  34. // Need this because MFC is incompatible with IE4/5
  35. #ifndef IPM_ISBLANK
  36. #define IPM_ISBLANK (WM_USER+105)
  37. #endif
  38. /////////////////////////////////////////////////////////////////////////////
  39. // CIpAddrParamsPage property page
  40. /////////////////////////////////////////////////////////////////////////////
  41. IMPLEMENT_DYNCREATE(CIpAddrParamsPage, CBasePropertyPage)
  42. /////////////////////////////////////////////////////////////////////////////
  43. // Message Maps
  44. BEGIN_MESSAGE_MAP(CIpAddrParamsPage, CBasePropertyPage)
  45. //{{AFX_MSG_MAP(CIpAddrParamsPage)
  46. ON_EN_CHANGE(IDC_PP_IPADDR_PARAMS_SUBNET_MASK, OnChangeSubnetMask)
  47. ON_EN_CHANGE(IDC_PP_IPADDR_PARAMS_ADDRESS, OnChangeIPAddress)
  48. ON_EN_KILLFOCUS(IDC_PP_IPADDR_PARAMS_ADDRESS, OnKillFocusIPAddress)
  49. ON_CBN_SELCHANGE(IDC_PP_IPADDR_PARAMS_NETWORK, OnChangeRequiredFields)
  50. //}}AFX_MSG_MAP
  51. // TODO: Modify the following lines to represent the data displayed on this page.
  52. ON_BN_CLICKED(IDC_PP_IPADDR_PARAMS_ENABLE_NETBIOS, OnChangeCtrl)
  53. END_MESSAGE_MAP()
  54. /////////////////////////////////////////////////////////////////////////////
  55. //++
  56. //
  57. // CIpAddrParamsPage::CIpAddrParamsPage
  58. //
  59. // Routine Description:
  60. // Default constructor.
  61. //
  62. // Arguments:
  63. // None.
  64. //
  65. // Return Value:
  66. // None.
  67. //
  68. //--
  69. /////////////////////////////////////////////////////////////////////////////
  70. CIpAddrParamsPage::CIpAddrParamsPage(void)
  71. : CBasePropertyPage(g_aHelpIDs_IDD_PP_IPADDR_PARAMETERS, g_aHelpIDs_IDD_WIZ_IPADDR_PARAMETERS)
  72. {
  73. // TODO: Modify the following lines to represent the data displayed on this page.
  74. //{{AFX_DATA_INIT(CIpAddrParamsPage)
  75. m_strIPAddress = _T("");
  76. m_strSubnetMask = _T("");
  77. m_strNetwork = _T("");
  78. m_bEnableNetBIOS = TRUE;
  79. //}}AFX_DATA_INIT
  80. // Setup the property array.
  81. {
  82. m_rgProps[epropNetwork].Set(REGPARAM_IPADDR_NETWORK, m_strNetwork, m_strPrevNetwork);
  83. m_rgProps[epropAddress].Set(REGPARAM_IPADDR_ADDRESS, m_strIPAddress, m_strPrevIPAddress);
  84. m_rgProps[epropSubnetMask].Set(REGPARAM_IPADDR_SUBNET_MASK, m_strSubnetMask, m_strPrevSubnetMask);
  85. m_rgProps[epropEnableNetBIOS].Set(REGPARAM_IPADDR_ENABLE_NETBIOS, m_bEnableNetBIOS, m_bPrevEnableNetBIOS);
  86. } // Setup the property array
  87. m_iddPropertyPage = IDD_PP_IPADDR_PARAMETERS;
  88. m_iddWizardPage = IDD_WIZ_IPADDR_PARAMETERS;
  89. m_bIsSubnetUpdatedManually = FALSE;
  90. m_bIsIPAddressModified = TRUE;
  91. } //*** CIpAddrParamsPage::CIpAddrParamsPage()
  92. /////////////////////////////////////////////////////////////////////////////
  93. //++
  94. //
  95. // CIpAddrParamsPage::~CIpAddrParamsPage
  96. //
  97. // Routine Description:
  98. // Destructor.
  99. //
  100. // Arguments:
  101. // None.
  102. //
  103. // Return Value:
  104. // None.
  105. //
  106. //--
  107. /////////////////////////////////////////////////////////////////////////////
  108. CIpAddrParamsPage::~CIpAddrParamsPage(void)
  109. {
  110. ClearNetworkObjectList();
  111. } //*** CIpAddrParamsPage::CIpAddrParamsPage()
  112. /////////////////////////////////////////////////////////////////////////////
  113. //++
  114. //
  115. // CIpAddrParamsPage::HrInit
  116. //
  117. // Routine Description:
  118. // Initialize the page.
  119. //
  120. // Arguments:
  121. // peo [IN OUT] Pointer to the extension object.
  122. //
  123. // Return Value:
  124. // S_OK Page initialized successfully.
  125. // hr Page failed to initialize.
  126. //
  127. //--
  128. /////////////////////////////////////////////////////////////////////////////
  129. HRESULT CIpAddrParamsPage::HrInit(IN OUT CExtObject * peo)
  130. {
  131. HRESULT _hr;
  132. CWaitCursor _wc;
  133. do
  134. {
  135. // Call the base class method.
  136. _hr = CBasePropertyPage::HrInit(peo);
  137. if (FAILED(_hr))
  138. break;
  139. //
  140. // Initialize common controls.
  141. //
  142. {
  143. #ifndef ICC_INTERNET_CLASSES
  144. #define ICC_INTERNET_CLASSES 0x00000800
  145. #endif
  146. static BOOL g_bInitializedCommonControls = FALSE;
  147. static INITCOMMONCONTROLSEX g_icce =
  148. {
  149. sizeof(g_icce),
  150. ICC_WIN95_CLASSES | ICC_INTERNET_CLASSES
  151. };
  152. if (!g_bInitializedCommonControls)
  153. {
  154. BOOL bSuccess;
  155. bSuccess = InitCommonControlsEx(&g_icce);
  156. _ASSERTE(bSuccess);
  157. g_bInitializedCommonControls = TRUE;
  158. } // if: common controls not initialized yet
  159. } // Initialize common controls
  160. } while ( 0 );
  161. return _hr;
  162. } //*** CIpAddrParamsPage::HrInit()
  163. /////////////////////////////////////////////////////////////////////////////
  164. //++
  165. //
  166. // CIpAddrParamsPage::DoDataExchange
  167. //
  168. // Routine Description:
  169. // Do data exchange between the dialog and the class.
  170. //
  171. // Arguments:
  172. // pDX [IN OUT] Data exchange object
  173. //
  174. // Return Value:
  175. // None.
  176. //
  177. //--
  178. /////////////////////////////////////////////////////////////////////////////
  179. void CIpAddrParamsPage::DoDataExchange(CDataExchange * pDX)
  180. {
  181. if (!pDX->m_bSaveAndValidate || !BSaved())
  182. {
  183. CString strMsg;
  184. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  185. // TODO: Modify the following lines to represent the data displayed on this page.
  186. //{{AFX_DATA_MAP(CIpAddrParamsPage)
  187. DDX_Control(pDX, IDC_PP_IPADDR_PARAMS_ENABLE_NETBIOS, m_chkEnableNetBIOS);
  188. DDX_Control(pDX, IDC_PP_IPADDR_PARAMS_NETWORK, m_cboxNetworks);
  189. DDX_Control(pDX, IDC_PP_IPADDR_PARAMS_SUBNET_MASK, m_editSubnetMask);
  190. DDX_Control(pDX, IDC_PP_IPADDR_PARAMS_ADDRESS, m_editIPAddress);
  191. DDX_Text(pDX, IDC_PP_IPADDR_PARAMS_ADDRESS, m_strIPAddress);
  192. DDX_Text(pDX, IDC_PP_IPADDR_PARAMS_SUBNET_MASK, m_strSubnetMask);
  193. DDX_CBString(pDX, IDC_PP_IPADDR_PARAMS_NETWORK, m_strNetwork);
  194. DDX_Check(pDX, IDC_PP_IPADDR_PARAMS_ENABLE_NETBIOS, m_bEnableNetBIOS);
  195. //}}AFX_DATA_MAP
  196. if (pDX->m_bSaveAndValidate)
  197. {
  198. if (!BBackPressed())
  199. {
  200. DDV_RequiredText(pDX, IDC_PP_IPADDR_PARAMS_NETWORK, IDC_PP_IPADDR_PARAMS_NETWORK_LABEL, m_strNetwork);
  201. DDV_RequiredText(pDX, IDC_PP_IPADDR_PARAMS_ADDRESS, IDC_PP_IPADDR_PARAMS_ADDRESS_LABEL, m_strIPAddress);
  202. DDV_RequiredText(pDX, IDC_PP_IPADDR_PARAMS_SUBNET_MASK, IDC_PP_IPADDR_PARAMS_SUBNET_MASK_LABEL, m_strSubnetMask);
  203. if (!BIsValidIpAddress(m_strIPAddress))
  204. {
  205. strMsg.FormatMessage(IDS_INVALID_IP_ADDRESS, m_strIPAddress);
  206. AfxMessageBox(strMsg, MB_OK | MB_ICONEXCLAMATION);
  207. DDX_Text(pDX, IDC_PP_IPADDR_PARAMS_ADDRESS, m_strIPAddress);
  208. strMsg.Empty();
  209. pDX->Fail();
  210. } // if: invalid address
  211. //
  212. // Make sure we process the IP address.
  213. // If we don't call it here, and the user pressed a tab button
  214. // while sitting in the IP address field, the EN_KILLFOCUS
  215. // message won't get processed until after this method returns.
  216. //
  217. if ( (m_strSubnetMask.GetLength() == 0)
  218. || (m_editSubnetMask.SendMessage(IPM_ISBLANK, 0, 0)) )
  219. {
  220. OnKillFocusIPAddress();
  221. } // if: subnet mask not specified
  222. if (!BIsValidSubnetMask(m_strSubnetMask))
  223. {
  224. strMsg.FormatMessage(IDS_INVALID_SUBNET_MASK, m_strSubnetMask);
  225. AfxMessageBox(strMsg, MB_OK | MB_ICONEXCLAMATION);
  226. DDX_Text(pDX, IDC_PP_IPADDR_PARAMS_SUBNET_MASK, m_strSubnetMask);
  227. strMsg.Empty();
  228. pDX->Fail();
  229. } // if: invalid subnet mask
  230. if (!BIsValidIpAddressAndSubnetMask(m_strIPAddress, m_strSubnetMask))
  231. {
  232. strMsg.FormatMessage(IDS_INVALID_ADDRESS_AND_SUBNET_MASK, m_strIPAddress, m_strSubnetMask);
  233. AfxMessageBox(strMsg, MB_OK | MB_ICONEXCLAMATION);
  234. DDX_Text(pDX, IDC_PP_IPADDR_PARAMS_ADDRESS, m_strIPAddress);
  235. strMsg.Empty();
  236. pDX->Fail();
  237. } // if: invalid address-mask combination
  238. if (BIsSubnetUpdatedManually())
  239. {
  240. int id = AfxMessageBox(IDS_IP_SUBNET_CANT_BE_VALIDATED, MB_YESNO | MB_DEFBUTTON2 | MB_ICONEXCLAMATION);
  241. if (id != IDYES)
  242. {
  243. DDX_Text(pDX, IDC_PP_IPADDR_PARAMS_SUBNET_MASK, m_strSubnetMask);
  244. pDX->Fail();
  245. } // if: subnet mask not valid
  246. } // if: subnet mask has been updated manually
  247. //
  248. // If there are Network Name resources dependent on this resource
  249. // and the EnableNetBIOS checkbox is unchecked, display a warning.
  250. //
  251. if (Peo()->BIsAnyNodeVersionLowerThanNT5() && !m_bEnableNetBIOS)
  252. {
  253. if (BIsNetNameProvider())
  254. {
  255. m_chkEnableNetBIOS.SetCheck(BST_CHECKED);
  256. AfxMessageBox(IDS_IP_PROVIDES_FOR_NETNAME, MB_ICONEXCLAMATION);
  257. DDX_Check(pDX, IDC_PP_IPADDR_PARAMS_ENABLE_NETBIOS, m_bEnableNetBIOS);
  258. pDX->Fail();
  259. } // if: resource provides for net name resource
  260. else
  261. {
  262. int id = AfxMessageBox(IDS_NETNAMES_MAY_NOT_WORK, MB_YESNO | MB_DEFBUTTON2 | MB_ICONEXCLAMATION);
  263. if (id != IDYES)
  264. {
  265. m_chkEnableNetBIOS.SetCheck(BST_CHECKED);
  266. DDX_Check(pDX, IDC_PP_IPADDR_PARAMS_ENABLE_NETBIOS, m_bEnableNetBIOS);
  267. pDX->Fail();
  268. } // if: user didn't continue
  269. } // else: resource doesn't provide for net name resource
  270. } // if: in NT4 Sp3 or Sp4 cluster with and no NetBIOS support
  271. } // if: Back button not pressed
  272. } // if: saving data
  273. } // if: not saving or haven't saved yet
  274. CBasePropertyPage::DoDataExchange(pDX);
  275. } //*** CIpAddrParamsPage::DoDataExchange()
  276. /////////////////////////////////////////////////////////////////////////////
  277. //++
  278. //
  279. // CIpAddrParamsPage::OnInitDialog
  280. //
  281. // Routine Description:
  282. // Handler for the WM_INITDIALOG message.
  283. //
  284. // Arguments:
  285. // None.
  286. //
  287. // Return Value:
  288. // TRUE We need the focus to be set for us.
  289. // FALSE We already set the focus to the proper control.
  290. //
  291. //--
  292. /////////////////////////////////////////////////////////////////////////////
  293. BOOL CIpAddrParamsPage::OnInitDialog(void)
  294. {
  295. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  296. CBasePropertyPage::OnInitDialog();
  297. // Collect networks and fill the combobox.
  298. {
  299. POSITION pos;
  300. CNetworkObject * pno;
  301. int inet;
  302. CollectNetworks();
  303. pos = m_lnetobjNetworks.GetHeadPosition();
  304. while (pos != NULL)
  305. {
  306. pno = m_lnetobjNetworks.GetNext(pos);
  307. ASSERT(pno != NULL);
  308. inet = m_cboxNetworks.AddString(pno->m_strName);
  309. ASSERT(inet != CB_ERR);
  310. m_cboxNetworks.SetItemDataPtr(inet, pno);
  311. } // while: more items in the list
  312. // Default to the first one if creating a new resource.
  313. if (BWizard())
  314. {
  315. if (m_lnetobjNetworks.GetCount() != 0)
  316. {
  317. pos = m_lnetobjNetworks.GetHeadPosition();
  318. pno = m_lnetobjNetworks.GetNext(pos);
  319. ASSERT(pno != NULL);
  320. m_strNetwork = pno->m_strName;
  321. } // if: list is not empty
  322. } // if: creating new resource
  323. // Set the current selection.
  324. UpdateData(FALSE /*bSaveAndValidate*/);
  325. } // Fill the combobox
  326. return TRUE; // return TRUE unless you set the focus to a control
  327. // EXCEPTION: OCX Property Pages should return FALSE
  328. } //*** CIpAddrParamsPage::OnInitDialog()
  329. /////////////////////////////////////////////////////////////////////////////
  330. //++
  331. //
  332. // CIpAddrParamsPage::OnSetActive
  333. //
  334. // Routine Description:
  335. // Handler for the PSN_SETACTIVE notification message.
  336. //
  337. // Arguments:
  338. // None.
  339. //
  340. // Return Value:
  341. // TRUE Page successfully initialized.
  342. // FALSE Page not initialized.
  343. //
  344. //--
  345. /////////////////////////////////////////////////////////////////////////////
  346. BOOL CIpAddrParamsPage::OnSetActive(void)
  347. {
  348. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  349. // Enable/disable the Next/Finish button.
  350. if (BWizard())
  351. {
  352. if ((m_strIPAddress.GetLength() == 0)
  353. || (m_strSubnetMask.GetLength() == 0)
  354. || (m_strNetwork.GetLength() == 0))
  355. EnableNext(FALSE);
  356. else
  357. EnableNext(TRUE);
  358. } // if: enable/disable the Next button
  359. return CBasePropertyPage::OnSetActive();
  360. } //*** CIpAddrParamsPage::OnSetActive()
  361. /////////////////////////////////////////////////////////////////////////////
  362. //++
  363. //
  364. // CIpAddrParamsPage::OnChangeRequiredFields
  365. //
  366. // Routine Description:
  367. // Handler for the EN_CHANGE message on required fields.
  368. //
  369. // Arguments:
  370. // None.
  371. //
  372. // Return Value:
  373. // TRUE Page successfully applied.
  374. // FALSE Error applying page.
  375. //
  376. //--
  377. /////////////////////////////////////////////////////////////////////////////
  378. void CIpAddrParamsPage::OnChangeRequiredFields(void)
  379. {
  380. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  381. OnChangeCtrl();
  382. if (BWizard())
  383. {
  384. if ((m_editIPAddress.GetWindowTextLength() == 0)
  385. || (m_editSubnetMask.GetWindowTextLength() == 0)
  386. || (m_cboxNetworks.GetCurSel() == CB_ERR))
  387. EnableNext(FALSE);
  388. else
  389. EnableNext(TRUE);
  390. } // if: in a wizard
  391. } //*** CIpAddrParamsPage::OnChangeRequiredFields()
  392. /////////////////////////////////////////////////////////////////////////////
  393. //++
  394. //
  395. // CIpAddrParamsPage::OnChangeSubnetMask
  396. //
  397. // Routine Description:
  398. // Handler for the EN_CHANGE message on the Subnet Mask field.
  399. //
  400. // Arguments:
  401. // None.
  402. //
  403. // Return Value:
  404. // TRUE Page successfully applied.
  405. // FALSE Error applying page.
  406. //
  407. //--
  408. /////////////////////////////////////////////////////////////////////////////
  409. void CIpAddrParamsPage::OnChangeSubnetMask(void)
  410. {
  411. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  412. OnChangeRequiredFields();
  413. m_bIsSubnetUpdatedManually = TRUE;
  414. } //*** CIpAddrParamsPage::OnChangeSubnetMask()
  415. /////////////////////////////////////////////////////////////////////////////
  416. //++
  417. //
  418. // CIpAddrParamsPage::OnChangeIPAddress
  419. //
  420. // Routine Description:
  421. // Handler for the EN_CHANGE message on the IP Address field.
  422. //
  423. // Arguments:
  424. // None.
  425. //
  426. // Return Value:
  427. // None.
  428. //
  429. //--
  430. /////////////////////////////////////////////////////////////////////////////
  431. void CIpAddrParamsPage::OnChangeIPAddress(void)
  432. {
  433. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  434. OnChangeRequiredFields();
  435. m_bIsIPAddressModified = TRUE;
  436. } //*** CIpAddrParamsPage::OnChangeIPAddress
  437. /////////////////////////////////////////////////////////////////////////////
  438. //++
  439. //
  440. // CIpAddrParamsPage::OnKillFocusIPAddress
  441. //
  442. // Routine Description:
  443. // Handler for the EN_KILLFOCUS command notification on
  444. // IDC_PP_IPADDR_PARAMS_ADDRESS.
  445. //
  446. // Arguments:
  447. // None.
  448. //
  449. // Return Value:
  450. // None.
  451. //
  452. //--
  453. /////////////////////////////////////////////////////////////////////////////
  454. void CIpAddrParamsPage::OnKillFocusIPAddress(void)
  455. {
  456. if ( m_bIsIPAddressModified != FALSE )
  457. {
  458. CString strAddress;
  459. CNetworkObject * pno;
  460. m_editIPAddress.GetWindowText(strAddress);
  461. if (strAddress.GetLength() == 0)
  462. {
  463. m_editIPAddress.SetSel(0, 0, FALSE);
  464. } // if: empty string
  465. else if (!BIsValidIpAddress(strAddress))
  466. {
  467. } // else if: invalid address
  468. else
  469. {
  470. pno = PnoNetworkFromIpAddress(strAddress);
  471. if (pno != NULL)
  472. {
  473. SelectNetwork(pno);
  474. } // if: network found
  475. else
  476. {
  477. // m_editSubnetMask.SetWindowText(_T(""));
  478. } // else: network not found
  479. } // else: valid address
  480. m_bIsIPAddressModified = FALSE;
  481. } // if: the IP Address field has been modified
  482. } //*** CIpAddrParamsPage::OnKillFocusIPAddress()
  483. /////////////////////////////////////////////////////////////////////////////
  484. //++
  485. //
  486. // CIpAddrParamsPage::CollectNetworks
  487. //
  488. // Routine Description:
  489. // Collect the networks in the cluster.
  490. //
  491. // Arguments:
  492. // None.
  493. //
  494. // Return Value:
  495. // None.
  496. //
  497. //--
  498. /////////////////////////////////////////////////////////////////////////////
  499. void CIpAddrParamsPage::CollectNetworks(void)
  500. {
  501. DWORD dwStatus;
  502. DWORD inet;
  503. CLUSTER_NETWORK_ROLE nRole;
  504. DWORD nType;
  505. DWORD cchNameCurrent;
  506. DWORD cchName = 256;
  507. LPWSTR pszName = NULL;
  508. LPWSTR psz;
  509. HCLUSENUM hclusenum = NULL;
  510. HNETWORK hnetwork = NULL;
  511. CClusPropList cpl;
  512. CNetworkObject * pno = NULL;
  513. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  514. // Clear the existing list.
  515. ClearNetworkObjectList();
  516. try
  517. {
  518. // Open an enumerator.
  519. hclusenum = ClusterOpenEnum(Hcluster(), CLUSTER_ENUM_NETWORK);
  520. if (hclusenum != NULL)
  521. {
  522. // Allocate a name buffer.
  523. pszName = new WCHAR[cchName];
  524. if ( pszName == NULL )
  525. goto Cleanup;
  526. for (inet = 0 ; ; inet++)
  527. {
  528. // Get the next network name.
  529. cchNameCurrent = cchName;
  530. dwStatus = ClusterEnum(hclusenum, inet, &nType, pszName, &cchNameCurrent);
  531. if (dwStatus == ERROR_MORE_DATA)
  532. {
  533. delete [] pszName;
  534. cchName = ++cchNameCurrent;
  535. pszName = new WCHAR[cchNameCurrent];
  536. if ( pszName == NULL )
  537. goto Cleanup;
  538. dwStatus = ClusterEnum(hclusenum, inet, &nType, pszName, &cchNameCurrent);
  539. } // if: buffer is too small
  540. if (dwStatus == ERROR_NO_MORE_ITEMS)
  541. break;
  542. // Open the network.
  543. if (hnetwork != NULL)
  544. CloseClusterNetwork(hnetwork);
  545. hnetwork = OpenClusterNetwork(Hcluster(), pszName);
  546. if (hnetwork == NULL)
  547. continue;
  548. // Get properties on the network.
  549. dwStatus = cpl.ScGetNetworkProperties(hnetwork, CLUSCTL_NETWORK_GET_COMMON_PROPERTIES);
  550. if (dwStatus != ERROR_SUCCESS)
  551. continue;
  552. // Find the Role property.
  553. dwStatus = ResUtilFindDwordProperty(
  554. cpl.PbPropList(),
  555. cpl.CbPropList(),
  556. CLUSREG_NAME_NET_ROLE,
  557. (DWORD *) &nRole
  558. );
  559. if (dwStatus != ERROR_SUCCESS)
  560. continue;
  561. // If this network is used for client access, add it to the list.
  562. if (nRole & ClusterNetworkRoleClientAccess)
  563. {
  564. // Allocate a network object and store common properties.
  565. pno = new CNetworkObject;
  566. if ( pno == NULL )
  567. goto Cleanup;
  568. pno->m_strName = pszName;
  569. pno->m_nRole = nRole;
  570. // Get read-only common properties.
  571. dwStatus = cpl.ScGetNetworkProperties(hnetwork, CLUSCTL_NETWORK_GET_RO_COMMON_PROPERTIES);
  572. if (dwStatus != ERROR_SUCCESS)
  573. {
  574. delete pno;
  575. pno = NULL;
  576. continue;
  577. } // if: error getting read-only common properties
  578. // Get the address property.
  579. dwStatus = ResUtilFindSzProperty(
  580. cpl.PbPropList(),
  581. cpl.CbPropList(),
  582. CLUSREG_NAME_NET_ADDRESS,
  583. &psz
  584. );
  585. if (dwStatus != ERROR_SUCCESS)
  586. {
  587. delete pno;
  588. pno = NULL;
  589. continue;
  590. } // if: error getting property
  591. pno->m_strAddress = psz;
  592. // Get the address mask property.
  593. dwStatus = ResUtilFindSzProperty(
  594. cpl.PbPropList(),
  595. cpl.CbPropList(),
  596. CLUSREG_NAME_NET_ADDRESS_MASK,
  597. &psz
  598. );
  599. if (dwStatus != ERROR_SUCCESS)
  600. {
  601. delete pno;
  602. pno = NULL;
  603. continue;
  604. } // if: error getting property
  605. pno->m_strAddressMask = psz;
  606. // Convert the strings to numbers.
  607. dwStatus = ClRtlTcpipStringToAddress(pno->m_strAddress, &pno->m_nAddress);
  608. if (dwStatus == ERROR_SUCCESS)
  609. dwStatus = ClRtlTcpipStringToAddress(pno->m_strAddressMask, &pno->m_nAddressMask);
  610. if (dwStatus != ERROR_SUCCESS)
  611. {
  612. delete pno;
  613. pno = NULL;
  614. continue;
  615. } // if: error getting property
  616. // Add the network to the list.
  617. m_lnetobjNetworks.AddTail(pno);
  618. pno = NULL;
  619. } // if: network is used for client access
  620. } // for: each network
  621. } // if: enumerator opened successful
  622. } // try
  623. catch (CException * pe)
  624. {
  625. pe->Delete();
  626. } // catch: CException
  627. Cleanup:
  628. delete pno;
  629. delete [] pszName;
  630. if (hclusenum != NULL)
  631. ClusterCloseEnum(hclusenum);
  632. if (hnetwork != NULL)
  633. CloseClusterNetwork(hnetwork);
  634. } //*** CIpAddrParamsPage::CollectNetworks()
  635. /////////////////////////////////////////////////////////////////////////////
  636. //++
  637. //
  638. // CIpAddrParamsPage::ClearNetworkObjectList
  639. //
  640. // Routine Description:
  641. // Remove all the entries in the network object list.
  642. //
  643. // Arguments:
  644. // None.
  645. //
  646. // Return Value:
  647. // None.
  648. //
  649. //--
  650. /////////////////////////////////////////////////////////////////////////////
  651. void CIpAddrParamsPage::ClearNetworkObjectList(void)
  652. {
  653. POSITION pos;
  654. CNetworkObject * pno;
  655. pos = m_lnetobjNetworks.GetHeadPosition();
  656. while (pos != NULL)
  657. {
  658. pno = m_lnetobjNetworks.GetNext(pos);
  659. ASSERT(pno != NULL);
  660. delete pno;
  661. } // while: more items in the list
  662. m_lnetobjNetworks.RemoveAll();
  663. } //*** CIpAddrParamsPage::ClearNetworkObjectList()
  664. /////////////////////////////////////////////////////////////////////////////
  665. //++
  666. //
  667. // CIpAddrParamsPage::PnoNetworkFromIpAddress
  668. //
  669. // Routine Description:
  670. // Find the network for the specified IP address.
  671. //
  672. // Arguments:
  673. // pszAddress [IN] IP address to match.
  674. //
  675. // Return Value:
  676. // NULL No matching network found.
  677. // pno Network that supports the specfied IP address.
  678. //
  679. //--
  680. /////////////////////////////////////////////////////////////////////////////
  681. CNetworkObject * CIpAddrParamsPage::PnoNetworkFromIpAddress(IN LPCWSTR pszAddress)
  682. {
  683. DWORD dwStatus;
  684. DWORD nAddress;
  685. POSITION pos;
  686. CNetworkObject * pno;
  687. // Convert the address to a number.
  688. dwStatus = ClRtlTcpipStringToAddress(pszAddress, &nAddress);
  689. if (dwStatus != ERROR_SUCCESS)
  690. return NULL;
  691. // Search the list for a matching address.
  692. pos = m_lnetobjNetworks.GetHeadPosition();
  693. while (pos != NULL)
  694. {
  695. pno = m_lnetobjNetworks.GetNext(pos);
  696. ASSERT(pno != NULL);
  697. if (ClRtlAreTcpipAddressesOnSameSubnet(nAddress, pno->m_nAddress, pno->m_nAddressMask))
  698. return pno;
  699. } // while: more items in the list
  700. return NULL;
  701. } //*** CIpAddrParamsPage::PnoNetworkFromIpAddress()
  702. /////////////////////////////////////////////////////////////////////////////
  703. //++
  704. //
  705. // CIpAddrParamsPage::SelectNetwork
  706. //
  707. // Routine Description:
  708. // Select the specified network in the network combobox, and set the
  709. // subnet mask in the subnet mask edit control.
  710. //
  711. // Arguments:
  712. // pno [IN] Network object structure for network to select.
  713. //
  714. // Return Value:
  715. // None.
  716. //
  717. //--
  718. /////////////////////////////////////////////////////////////////////////////
  719. void CIpAddrParamsPage::SelectNetwork(IN CNetworkObject * pno)
  720. {
  721. int inet;
  722. CString strSubnetMask;
  723. ASSERT(pno != NULL);
  724. // Find the proper item in the checkbox.
  725. inet = m_cboxNetworks.FindStringExact(-1, pno->m_strName);
  726. if (inet != CB_ERR)
  727. {
  728. m_cboxNetworks.SetCurSel(inet);
  729. m_editSubnetMask.GetWindowText(strSubnetMask);
  730. if (strSubnetMask != pno->m_strAddressMask)
  731. m_editSubnetMask.SetWindowText(pno->m_strAddressMask);
  732. m_bIsSubnetUpdatedManually = FALSE;
  733. m_strSubnetMask = pno->m_strAddressMask;
  734. m_strNetwork = pno->m_strName;
  735. } // if: match found
  736. } //*** CIpAddrParamsPage::SelectNetwork()
  737. /////////////////////////////////////////////////////////////////////////////
  738. //++
  739. //
  740. // CIpAddrParamsPage::BIsNetNameProvider
  741. //
  742. // Routine Description:
  743. // Determine if a network name resource is dependent on this resource.
  744. //
  745. // Arguments:
  746. // None.
  747. //
  748. // Return Value:
  749. // None.
  750. //
  751. //--
  752. /////////////////////////////////////////////////////////////////////////////
  753. BOOL CIpAddrParamsPage::BIsNetNameProvider(void)
  754. {
  755. DWORD dwStatus = ERROR_SUCCESS;
  756. BOOL bIsNetNameProvider = FALSE;
  757. HRESENUM hresenum;
  758. HRESOURCE hres = NULL;
  759. DWORD ires;
  760. DWORD dwType;
  761. DWORD cchName;
  762. DWORD cchNameSize;
  763. DWORD cbResType;
  764. DWORD cbResTypeSize;
  765. LPWSTR pszName = NULL;
  766. LPWSTR pszResType = NULL;
  767. // Open the provides-for enumerator.
  768. hresenum = ClusterResourceOpenEnum(
  769. Peo()->PrdResData()->m_hresource,
  770. CLUSTER_RESOURCE_ENUM_PROVIDES
  771. );
  772. if (hresenum == NULL)
  773. return NULL;
  774. // Allocate a default size name and type buffer.
  775. cchNameSize = 512;
  776. pszName = new WCHAR[cchNameSize];
  777. if ( pszName == NULL )
  778. {
  779. dwStatus = ERROR_OUTOFMEMORY;
  780. goto Cleanup;
  781. }
  782. cbResTypeSize = 256;
  783. pszResType = new WCHAR[cbResTypeSize / 2];
  784. if ( pszResType == NULL )
  785. {
  786. dwStatus = ERROR_OUTOFMEMORY;
  787. goto Cleanup;
  788. }
  789. for (ires = 0 ; ; ires++)
  790. {
  791. // Get the name of the next resource.
  792. cchName = cchNameSize;
  793. dwStatus = ClusterResourceEnum(
  794. hresenum,
  795. ires,
  796. &dwType,
  797. pszName,
  798. &cchName
  799. );
  800. if (dwStatus == ERROR_MORE_DATA)
  801. {
  802. delete [] pszName;
  803. cchNameSize = cchName;
  804. pszName = new WCHAR[cchNameSize];
  805. if ( pszName == NULL )
  806. {
  807. dwStatus = ERROR_OUTOFMEMORY;
  808. goto Cleanup;
  809. }
  810. dwStatus = ClusterResourceEnum(
  811. hresenum,
  812. ires,
  813. &dwType,
  814. pszName,
  815. &cchName
  816. );
  817. } // if: name buffer too small
  818. if (dwStatus != ERROR_SUCCESS)
  819. break;
  820. // Open the resource.
  821. hres = OpenClusterResource(Hcluster(), pszName);
  822. if (hres == NULL)
  823. {
  824. dwStatus = GetLastError();
  825. break;
  826. } // if: error opening the resource
  827. // Get the type of the resource.
  828. dwStatus = ClusterResourceControl(
  829. hres,
  830. NULL,
  831. CLUSCTL_RESOURCE_GET_RESOURCE_TYPE,
  832. NULL,
  833. 0,
  834. pszResType,
  835. cbResTypeSize,
  836. &cbResType
  837. );
  838. if (dwStatus == ERROR_MORE_DATA)
  839. {
  840. delete [] pszResType;
  841. cbResTypeSize = cbResType;
  842. pszResType = new WCHAR[cbResTypeSize / 2];
  843. if ( pszResType == NULL )
  844. {
  845. dwStatus = ERROR_OUTOFMEMORY;
  846. goto Cleanup;
  847. }
  848. dwStatus = ClusterResourceControl(
  849. hres,
  850. NULL,
  851. CLUSCTL_RESOURCE_GET_RESOURCE_TYPE,
  852. NULL,
  853. 0,
  854. pszResType,
  855. cbResTypeSize,
  856. &cbResType
  857. );
  858. } // if: resource type buffer too small
  859. if (dwStatus != ERROR_SUCCESS)
  860. break;
  861. // If this is a Network Name resource, we're done.
  862. if (lstrcmpiW(pszResType, CLUS_RESTYPE_NAME_NETNAME) == 0)
  863. {
  864. bIsNetNameProvider = TRUE;
  865. break;
  866. } // if: resource is a Network Name
  867. // Not storage-class resource.
  868. CloseClusterResource(hres);
  869. hres = NULL;
  870. } // for each resource on which we are dependent
  871. Cleanup:
  872. // Handle errors.
  873. if ( hres != NULL )
  874. {
  875. CloseClusterResource(hres);
  876. hres = NULL;
  877. } // if: error getting resource
  878. ClusterResourceCloseEnum(hresenum);
  879. delete [] pszName;
  880. delete [] pszResType;
  881. return bIsNetNameProvider;
  882. } //*** CIpAddrParamsPage::BIsNetNameProvider()