///////////////////////////////////////////////////////////////////////////// // // Copyright (c) 1996-2000 Microsoft Corporation // // Module Name: // IpAddr.cpp // // Abstract: // Implementation of the CIpAddrParamsPage class. // // Author: // David Potter (davidp) June 5, 1996 // // Revision History: // // Notes: // ///////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include #include #include "CluAdmX.h" #include "ExtObj.h" #include "IpAddr.h" #include "DDxDDv.h" #include "HelpData.h" #include "PropList.h" #include "AdmNetUtils.h" // for BIsValidxxx net utility functions #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif // Need this because MFC is incompatible with IE4/5 #ifndef IPM_ISBLANK #define IPM_ISBLANK (WM_USER+105) #endif ///////////////////////////////////////////////////////////////////////////// // CIpAddrParamsPage property page ///////////////////////////////////////////////////////////////////////////// IMPLEMENT_DYNCREATE(CIpAddrParamsPage, CBasePropertyPage) ///////////////////////////////////////////////////////////////////////////// // Message Maps BEGIN_MESSAGE_MAP(CIpAddrParamsPage, CBasePropertyPage) //{{AFX_MSG_MAP(CIpAddrParamsPage) ON_EN_CHANGE(IDC_PP_IPADDR_PARAMS_SUBNET_MASK, OnChangeSubnetMask) ON_EN_CHANGE(IDC_PP_IPADDR_PARAMS_ADDRESS, OnChangeIPAddress) ON_EN_KILLFOCUS(IDC_PP_IPADDR_PARAMS_ADDRESS, OnKillFocusIPAddress) ON_CBN_SELCHANGE(IDC_PP_IPADDR_PARAMS_NETWORK, OnChangeRequiredFields) //}}AFX_MSG_MAP // TODO: Modify the following lines to represent the data displayed on this page. ON_BN_CLICKED(IDC_PP_IPADDR_PARAMS_ENABLE_NETBIOS, OnChangeCtrl) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// //++ // // CIpAddrParamsPage::CIpAddrParamsPage // // Routine Description: // Default constructor. // // Arguments: // None. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// CIpAddrParamsPage::CIpAddrParamsPage(void) : CBasePropertyPage(g_aHelpIDs_IDD_PP_IPADDR_PARAMETERS, g_aHelpIDs_IDD_WIZ_IPADDR_PARAMETERS) { // TODO: Modify the following lines to represent the data displayed on this page. //{{AFX_DATA_INIT(CIpAddrParamsPage) m_strIPAddress = _T(""); m_strSubnetMask = _T(""); m_strNetwork = _T(""); m_bEnableNetBIOS = TRUE; //}}AFX_DATA_INIT // Setup the property array. { m_rgProps[epropNetwork].Set(REGPARAM_IPADDR_NETWORK, m_strNetwork, m_strPrevNetwork); m_rgProps[epropAddress].Set(REGPARAM_IPADDR_ADDRESS, m_strIPAddress, m_strPrevIPAddress); m_rgProps[epropSubnetMask].Set(REGPARAM_IPADDR_SUBNET_MASK, m_strSubnetMask, m_strPrevSubnetMask); m_rgProps[epropEnableNetBIOS].Set(REGPARAM_IPADDR_ENABLE_NETBIOS, m_bEnableNetBIOS, m_bPrevEnableNetBIOS); } // Setup the property array m_iddPropertyPage = IDD_PP_IPADDR_PARAMETERS; m_iddWizardPage = IDD_WIZ_IPADDR_PARAMETERS; m_bIsSubnetUpdatedManually = FALSE; m_bIsIPAddressModified = TRUE; } //*** CIpAddrParamsPage::CIpAddrParamsPage() ///////////////////////////////////////////////////////////////////////////// //++ // // CIpAddrParamsPage::~CIpAddrParamsPage // // Routine Description: // Destructor. // // Arguments: // None. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// CIpAddrParamsPage::~CIpAddrParamsPage(void) { ClearNetworkObjectList(); } //*** CIpAddrParamsPage::CIpAddrParamsPage() ///////////////////////////////////////////////////////////////////////////// //++ // // CIpAddrParamsPage::HrInit // // Routine Description: // Initialize the page. // // Arguments: // peo [IN OUT] Pointer to the extension object. // // Return Value: // S_OK Page initialized successfully. // hr Page failed to initialize. // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT CIpAddrParamsPage::HrInit(IN OUT CExtObject * peo) { HRESULT _hr; CWaitCursor _wc; do { // Call the base class method. _hr = CBasePropertyPage::HrInit(peo); if (FAILED(_hr)) break; // // Initialize common controls. // { #ifndef ICC_INTERNET_CLASSES #define ICC_INTERNET_CLASSES 0x00000800 #endif static BOOL g_bInitializedCommonControls = FALSE; static INITCOMMONCONTROLSEX g_icce = { sizeof(g_icce), ICC_WIN95_CLASSES | ICC_INTERNET_CLASSES }; if (!g_bInitializedCommonControls) { BOOL bSuccess; bSuccess = InitCommonControlsEx(&g_icce); _ASSERTE(bSuccess); g_bInitializedCommonControls = TRUE; } // if: common controls not initialized yet } // Initialize common controls } while ( 0 ); return _hr; } //*** CIpAddrParamsPage::HrInit() ///////////////////////////////////////////////////////////////////////////// //++ // // CIpAddrParamsPage::DoDataExchange // // Routine Description: // Do data exchange between the dialog and the class. // // Arguments: // pDX [IN OUT] Data exchange object // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// void CIpAddrParamsPage::DoDataExchange(CDataExchange * pDX) { if (!pDX->m_bSaveAndValidate || !BSaved()) { CString strMsg; AFX_MANAGE_STATE(AfxGetStaticModuleState()); // TODO: Modify the following lines to represent the data displayed on this page. //{{AFX_DATA_MAP(CIpAddrParamsPage) DDX_Control(pDX, IDC_PP_IPADDR_PARAMS_ENABLE_NETBIOS, m_chkEnableNetBIOS); DDX_Control(pDX, IDC_PP_IPADDR_PARAMS_NETWORK, m_cboxNetworks); DDX_Control(pDX, IDC_PP_IPADDR_PARAMS_SUBNET_MASK, m_editSubnetMask); DDX_Control(pDX, IDC_PP_IPADDR_PARAMS_ADDRESS, m_editIPAddress); DDX_Text(pDX, IDC_PP_IPADDR_PARAMS_ADDRESS, m_strIPAddress); DDX_Text(pDX, IDC_PP_IPADDR_PARAMS_SUBNET_MASK, m_strSubnetMask); DDX_CBString(pDX, IDC_PP_IPADDR_PARAMS_NETWORK, m_strNetwork); DDX_Check(pDX, IDC_PP_IPADDR_PARAMS_ENABLE_NETBIOS, m_bEnableNetBIOS); //}}AFX_DATA_MAP if (pDX->m_bSaveAndValidate) { if (!BBackPressed()) { DDV_RequiredText(pDX, IDC_PP_IPADDR_PARAMS_NETWORK, IDC_PP_IPADDR_PARAMS_NETWORK_LABEL, m_strNetwork); DDV_RequiredText(pDX, IDC_PP_IPADDR_PARAMS_ADDRESS, IDC_PP_IPADDR_PARAMS_ADDRESS_LABEL, m_strIPAddress); DDV_RequiredText(pDX, IDC_PP_IPADDR_PARAMS_SUBNET_MASK, IDC_PP_IPADDR_PARAMS_SUBNET_MASK_LABEL, m_strSubnetMask); if (!BIsValidIpAddress(m_strIPAddress)) { strMsg.FormatMessage(IDS_INVALID_IP_ADDRESS, m_strIPAddress); AfxMessageBox(strMsg, MB_OK | MB_ICONEXCLAMATION); DDX_Text(pDX, IDC_PP_IPADDR_PARAMS_ADDRESS, m_strIPAddress); strMsg.Empty(); pDX->Fail(); } // if: invalid address // // Make sure we process the IP address. // If we don't call it here, and the user pressed a tab button // while sitting in the IP address field, the EN_KILLFOCUS // message won't get processed until after this method returns. // if ( (m_strSubnetMask.GetLength() == 0) || (m_editSubnetMask.SendMessage(IPM_ISBLANK, 0, 0)) ) { OnKillFocusIPAddress(); } // if: subnet mask not specified if (!BIsValidSubnetMask(m_strSubnetMask)) { strMsg.FormatMessage(IDS_INVALID_SUBNET_MASK, m_strSubnetMask); AfxMessageBox(strMsg, MB_OK | MB_ICONEXCLAMATION); DDX_Text(pDX, IDC_PP_IPADDR_PARAMS_SUBNET_MASK, m_strSubnetMask); strMsg.Empty(); pDX->Fail(); } // if: invalid subnet mask if (!BIsValidIpAddressAndSubnetMask(m_strIPAddress, m_strSubnetMask)) { strMsg.FormatMessage(IDS_INVALID_ADDRESS_AND_SUBNET_MASK, m_strIPAddress, m_strSubnetMask); AfxMessageBox(strMsg, MB_OK | MB_ICONEXCLAMATION); DDX_Text(pDX, IDC_PP_IPADDR_PARAMS_ADDRESS, m_strIPAddress); strMsg.Empty(); pDX->Fail(); } // if: invalid address-mask combination if (BIsSubnetUpdatedManually()) { int id = AfxMessageBox(IDS_IP_SUBNET_CANT_BE_VALIDATED, MB_YESNO | MB_DEFBUTTON2 | MB_ICONEXCLAMATION); if (id != IDYES) { DDX_Text(pDX, IDC_PP_IPADDR_PARAMS_SUBNET_MASK, m_strSubnetMask); pDX->Fail(); } // if: subnet mask not valid } // if: subnet mask has been updated manually // // If there are Network Name resources dependent on this resource // and the EnableNetBIOS checkbox is unchecked, display a warning. // if (Peo()->BIsAnyNodeVersionLowerThanNT5() && !m_bEnableNetBIOS) { if (BIsNetNameProvider()) { m_chkEnableNetBIOS.SetCheck(BST_CHECKED); AfxMessageBox(IDS_IP_PROVIDES_FOR_NETNAME, MB_ICONEXCLAMATION); DDX_Check(pDX, IDC_PP_IPADDR_PARAMS_ENABLE_NETBIOS, m_bEnableNetBIOS); pDX->Fail(); } // if: resource provides for net name resource else { int id = AfxMessageBox(IDS_NETNAMES_MAY_NOT_WORK, MB_YESNO | MB_DEFBUTTON2 | MB_ICONEXCLAMATION); if (id != IDYES) { m_chkEnableNetBIOS.SetCheck(BST_CHECKED); DDX_Check(pDX, IDC_PP_IPADDR_PARAMS_ENABLE_NETBIOS, m_bEnableNetBIOS); pDX->Fail(); } // if: user didn't continue } // else: resource doesn't provide for net name resource } // if: in NT4 Sp3 or Sp4 cluster with and no NetBIOS support } // if: Back button not pressed } // if: saving data } // if: not saving or haven't saved yet CBasePropertyPage::DoDataExchange(pDX); } //*** CIpAddrParamsPage::DoDataExchange() ///////////////////////////////////////////////////////////////////////////// //++ // // CIpAddrParamsPage::OnInitDialog // // Routine Description: // Handler for the WM_INITDIALOG message. // // Arguments: // None. // // Return Value: // TRUE We need the focus to be set for us. // FALSE We already set the focus to the proper control. // //-- ///////////////////////////////////////////////////////////////////////////// BOOL CIpAddrParamsPage::OnInitDialog(void) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); CBasePropertyPage::OnInitDialog(); // Collect networks and fill the combobox. { POSITION pos; CNetworkObject * pno; int inet; CollectNetworks(); pos = m_lnetobjNetworks.GetHeadPosition(); while (pos != NULL) { pno = m_lnetobjNetworks.GetNext(pos); ASSERT(pno != NULL); inet = m_cboxNetworks.AddString(pno->m_strName); ASSERT(inet != CB_ERR); m_cboxNetworks.SetItemDataPtr(inet, pno); } // while: more items in the list // Default to the first one if creating a new resource. if (BWizard()) { if (m_lnetobjNetworks.GetCount() != 0) { pos = m_lnetobjNetworks.GetHeadPosition(); pno = m_lnetobjNetworks.GetNext(pos); ASSERT(pno != NULL); m_strNetwork = pno->m_strName; } // if: list is not empty } // if: creating new resource // Set the current selection. UpdateData(FALSE /*bSaveAndValidate*/); } // Fill the combobox return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE } //*** CIpAddrParamsPage::OnInitDialog() ///////////////////////////////////////////////////////////////////////////// //++ // // CIpAddrParamsPage::OnSetActive // // Routine Description: // Handler for the PSN_SETACTIVE notification message. // // Arguments: // None. // // Return Value: // TRUE Page successfully initialized. // FALSE Page not initialized. // //-- ///////////////////////////////////////////////////////////////////////////// BOOL CIpAddrParamsPage::OnSetActive(void) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); // Enable/disable the Next/Finish button. if (BWizard()) { if ((m_strIPAddress.GetLength() == 0) || (m_strSubnetMask.GetLength() == 0) || (m_strNetwork.GetLength() == 0)) EnableNext(FALSE); else EnableNext(TRUE); } // if: enable/disable the Next button return CBasePropertyPage::OnSetActive(); } //*** CIpAddrParamsPage::OnSetActive() ///////////////////////////////////////////////////////////////////////////// //++ // // CIpAddrParamsPage::OnChangeRequiredFields // // Routine Description: // Handler for the EN_CHANGE message on required fields. // // Arguments: // None. // // Return Value: // TRUE Page successfully applied. // FALSE Error applying page. // //-- ///////////////////////////////////////////////////////////////////////////// void CIpAddrParamsPage::OnChangeRequiredFields(void) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); OnChangeCtrl(); if (BWizard()) { if ((m_editIPAddress.GetWindowTextLength() == 0) || (m_editSubnetMask.GetWindowTextLength() == 0) || (m_cboxNetworks.GetCurSel() == CB_ERR)) EnableNext(FALSE); else EnableNext(TRUE); } // if: in a wizard } //*** CIpAddrParamsPage::OnChangeRequiredFields() ///////////////////////////////////////////////////////////////////////////// //++ // // CIpAddrParamsPage::OnChangeSubnetMask // // Routine Description: // Handler for the EN_CHANGE message on the Subnet Mask field. // // Arguments: // None. // // Return Value: // TRUE Page successfully applied. // FALSE Error applying page. // //-- ///////////////////////////////////////////////////////////////////////////// void CIpAddrParamsPage::OnChangeSubnetMask(void) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); OnChangeRequiredFields(); m_bIsSubnetUpdatedManually = TRUE; } //*** CIpAddrParamsPage::OnChangeSubnetMask() ///////////////////////////////////////////////////////////////////////////// //++ // // CIpAddrParamsPage::OnChangeIPAddress // // Routine Description: // Handler for the EN_CHANGE message on the IP Address field. // // Arguments: // None. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// void CIpAddrParamsPage::OnChangeIPAddress(void) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); OnChangeRequiredFields(); m_bIsIPAddressModified = TRUE; } //*** CIpAddrParamsPage::OnChangeIPAddress ///////////////////////////////////////////////////////////////////////////// //++ // // CIpAddrParamsPage::OnKillFocusIPAddress // // Routine Description: // Handler for the EN_KILLFOCUS command notification on // IDC_PP_IPADDR_PARAMS_ADDRESS. // // Arguments: // None. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// void CIpAddrParamsPage::OnKillFocusIPAddress(void) { if ( m_bIsIPAddressModified != FALSE ) { CString strAddress; CNetworkObject * pno; m_editIPAddress.GetWindowText(strAddress); if (strAddress.GetLength() == 0) { m_editIPAddress.SetSel(0, 0, FALSE); } // if: empty string else if (!BIsValidIpAddress(strAddress)) { } // else if: invalid address else { pno = PnoNetworkFromIpAddress(strAddress); if (pno != NULL) { SelectNetwork(pno); } // if: network found else { // m_editSubnetMask.SetWindowText(_T("")); } // else: network not found } // else: valid address m_bIsIPAddressModified = FALSE; } // if: the IP Address field has been modified } //*** CIpAddrParamsPage::OnKillFocusIPAddress() ///////////////////////////////////////////////////////////////////////////// //++ // // CIpAddrParamsPage::CollectNetworks // // Routine Description: // Collect the networks in the cluster. // // Arguments: // None. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// void CIpAddrParamsPage::CollectNetworks(void) { DWORD dwStatus; DWORD inet; CLUSTER_NETWORK_ROLE nRole; DWORD nType; DWORD cchNameCurrent; DWORD cchName = 256; LPWSTR pszName = NULL; LPWSTR psz; HCLUSENUM hclusenum = NULL; HNETWORK hnetwork = NULL; CClusPropList cpl; CNetworkObject * pno = NULL; AFX_MANAGE_STATE(AfxGetStaticModuleState()); // Clear the existing list. ClearNetworkObjectList(); try { // Open an enumerator. hclusenum = ClusterOpenEnum(Hcluster(), CLUSTER_ENUM_NETWORK); if (hclusenum != NULL) { // Allocate a name buffer. pszName = new WCHAR[cchName]; if ( pszName == NULL ) goto Cleanup; for (inet = 0 ; ; inet++) { // Get the next network name. cchNameCurrent = cchName; dwStatus = ClusterEnum(hclusenum, inet, &nType, pszName, &cchNameCurrent); if (dwStatus == ERROR_MORE_DATA) { delete [] pszName; cchName = ++cchNameCurrent; pszName = new WCHAR[cchNameCurrent]; if ( pszName == NULL ) goto Cleanup; dwStatus = ClusterEnum(hclusenum, inet, &nType, pszName, &cchNameCurrent); } // if: buffer is too small if (dwStatus == ERROR_NO_MORE_ITEMS) break; // Open the network. if (hnetwork != NULL) CloseClusterNetwork(hnetwork); hnetwork = OpenClusterNetwork(Hcluster(), pszName); if (hnetwork == NULL) continue; // Get properties on the network. dwStatus = cpl.ScGetNetworkProperties(hnetwork, CLUSCTL_NETWORK_GET_COMMON_PROPERTIES); if (dwStatus != ERROR_SUCCESS) continue; // Find the Role property. dwStatus = ResUtilFindDwordProperty( cpl.PbPropList(), cpl.CbPropList(), CLUSREG_NAME_NET_ROLE, (DWORD *) &nRole ); if (dwStatus != ERROR_SUCCESS) continue; // If this network is used for client access, add it to the list. if (nRole & ClusterNetworkRoleClientAccess) { // Allocate a network object and store common properties. pno = new CNetworkObject; if ( pno == NULL ) goto Cleanup; pno->m_strName = pszName; pno->m_nRole = nRole; // Get read-only common properties. dwStatus = cpl.ScGetNetworkProperties(hnetwork, CLUSCTL_NETWORK_GET_RO_COMMON_PROPERTIES); if (dwStatus != ERROR_SUCCESS) { delete pno; pno = NULL; continue; } // if: error getting read-only common properties // Get the address property. dwStatus = ResUtilFindSzProperty( cpl.PbPropList(), cpl.CbPropList(), CLUSREG_NAME_NET_ADDRESS, &psz ); if (dwStatus != ERROR_SUCCESS) { delete pno; pno = NULL; continue; } // if: error getting property pno->m_strAddress = psz; // Get the address mask property. dwStatus = ResUtilFindSzProperty( cpl.PbPropList(), cpl.CbPropList(), CLUSREG_NAME_NET_ADDRESS_MASK, &psz ); if (dwStatus != ERROR_SUCCESS) { delete pno; pno = NULL; continue; } // if: error getting property pno->m_strAddressMask = psz; // Convert the strings to numbers. dwStatus = ClRtlTcpipStringToAddress(pno->m_strAddress, &pno->m_nAddress); if (dwStatus == ERROR_SUCCESS) dwStatus = ClRtlTcpipStringToAddress(pno->m_strAddressMask, &pno->m_nAddressMask); if (dwStatus != ERROR_SUCCESS) { delete pno; pno = NULL; continue; } // if: error getting property // Add the network to the list. m_lnetobjNetworks.AddTail(pno); pno = NULL; } // if: network is used for client access } // for: each network } // if: enumerator opened successful } // try catch (CException * pe) { pe->Delete(); } // catch: CException Cleanup: delete pno; delete [] pszName; if (hclusenum != NULL) ClusterCloseEnum(hclusenum); if (hnetwork != NULL) CloseClusterNetwork(hnetwork); } //*** CIpAddrParamsPage::CollectNetworks() ///////////////////////////////////////////////////////////////////////////// //++ // // CIpAddrParamsPage::ClearNetworkObjectList // // Routine Description: // Remove all the entries in the network object list. // // Arguments: // None. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// void CIpAddrParamsPage::ClearNetworkObjectList(void) { POSITION pos; CNetworkObject * pno; pos = m_lnetobjNetworks.GetHeadPosition(); while (pos != NULL) { pno = m_lnetobjNetworks.GetNext(pos); ASSERT(pno != NULL); delete pno; } // while: more items in the list m_lnetobjNetworks.RemoveAll(); } //*** CIpAddrParamsPage::ClearNetworkObjectList() ///////////////////////////////////////////////////////////////////////////// //++ // // CIpAddrParamsPage::PnoNetworkFromIpAddress // // Routine Description: // Find the network for the specified IP address. // // Arguments: // pszAddress [IN] IP address to match. // // Return Value: // NULL No matching network found. // pno Network that supports the specfied IP address. // //-- ///////////////////////////////////////////////////////////////////////////// CNetworkObject * CIpAddrParamsPage::PnoNetworkFromIpAddress(IN LPCWSTR pszAddress) { DWORD dwStatus; DWORD nAddress; POSITION pos; CNetworkObject * pno; // Convert the address to a number. dwStatus = ClRtlTcpipStringToAddress(pszAddress, &nAddress); if (dwStatus != ERROR_SUCCESS) return NULL; // Search the list for a matching address. pos = m_lnetobjNetworks.GetHeadPosition(); while (pos != NULL) { pno = m_lnetobjNetworks.GetNext(pos); ASSERT(pno != NULL); if (ClRtlAreTcpipAddressesOnSameSubnet(nAddress, pno->m_nAddress, pno->m_nAddressMask)) return pno; } // while: more items in the list return NULL; } //*** CIpAddrParamsPage::PnoNetworkFromIpAddress() ///////////////////////////////////////////////////////////////////////////// //++ // // CIpAddrParamsPage::SelectNetwork // // Routine Description: // Select the specified network in the network combobox, and set the // subnet mask in the subnet mask edit control. // // Arguments: // pno [IN] Network object structure for network to select. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// void CIpAddrParamsPage::SelectNetwork(IN CNetworkObject * pno) { int inet; CString strSubnetMask; ASSERT(pno != NULL); // Find the proper item in the checkbox. inet = m_cboxNetworks.FindStringExact(-1, pno->m_strName); if (inet != CB_ERR) { m_cboxNetworks.SetCurSel(inet); m_editSubnetMask.GetWindowText(strSubnetMask); if (strSubnetMask != pno->m_strAddressMask) m_editSubnetMask.SetWindowText(pno->m_strAddressMask); m_bIsSubnetUpdatedManually = FALSE; m_strSubnetMask = pno->m_strAddressMask; m_strNetwork = pno->m_strName; } // if: match found } //*** CIpAddrParamsPage::SelectNetwork() ///////////////////////////////////////////////////////////////////////////// //++ // // CIpAddrParamsPage::BIsNetNameProvider // // Routine Description: // Determine if a network name resource is dependent on this resource. // // Arguments: // None. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// BOOL CIpAddrParamsPage::BIsNetNameProvider(void) { DWORD dwStatus = ERROR_SUCCESS; BOOL bIsNetNameProvider = FALSE; HRESENUM hresenum; HRESOURCE hres = NULL; DWORD ires; DWORD dwType; DWORD cchName; DWORD cchNameSize; DWORD cbResType; DWORD cbResTypeSize; LPWSTR pszName = NULL; LPWSTR pszResType = NULL; // Open the provides-for enumerator. hresenum = ClusterResourceOpenEnum( Peo()->PrdResData()->m_hresource, CLUSTER_RESOURCE_ENUM_PROVIDES ); if (hresenum == NULL) return NULL; // Allocate a default size name and type buffer. cchNameSize = 512; pszName = new WCHAR[cchNameSize]; if ( pszName == NULL ) { dwStatus = ERROR_OUTOFMEMORY; goto Cleanup; } cbResTypeSize = 256; pszResType = new WCHAR[cbResTypeSize / 2]; if ( pszResType == NULL ) { dwStatus = ERROR_OUTOFMEMORY; goto Cleanup; } for (ires = 0 ; ; ires++) { // Get the name of the next resource. cchName = cchNameSize; dwStatus = ClusterResourceEnum( hresenum, ires, &dwType, pszName, &cchName ); if (dwStatus == ERROR_MORE_DATA) { delete [] pszName; cchNameSize = cchName; pszName = new WCHAR[cchNameSize]; if ( pszName == NULL ) { dwStatus = ERROR_OUTOFMEMORY; goto Cleanup; } dwStatus = ClusterResourceEnum( hresenum, ires, &dwType, pszName, &cchName ); } // if: name buffer too small if (dwStatus != ERROR_SUCCESS) break; // Open the resource. hres = OpenClusterResource(Hcluster(), pszName); if (hres == NULL) { dwStatus = GetLastError(); break; } // if: error opening the resource // Get the type of the resource. dwStatus = ClusterResourceControl( hres, NULL, CLUSCTL_RESOURCE_GET_RESOURCE_TYPE, NULL, 0, pszResType, cbResTypeSize, &cbResType ); if (dwStatus == ERROR_MORE_DATA) { delete [] pszResType; cbResTypeSize = cbResType; pszResType = new WCHAR[cbResTypeSize / 2]; if ( pszResType == NULL ) { dwStatus = ERROR_OUTOFMEMORY; goto Cleanup; } dwStatus = ClusterResourceControl( hres, NULL, CLUSCTL_RESOURCE_GET_RESOURCE_TYPE, NULL, 0, pszResType, cbResTypeSize, &cbResType ); } // if: resource type buffer too small if (dwStatus != ERROR_SUCCESS) break; // If this is a Network Name resource, we're done. if (lstrcmpiW(pszResType, CLUS_RESTYPE_NAME_NETNAME) == 0) { bIsNetNameProvider = TRUE; break; } // if: resource is a Network Name // Not storage-class resource. CloseClusterResource(hres); hres = NULL; } // for each resource on which we are dependent Cleanup: // Handle errors. if ( hres != NULL ) { CloseClusterResource(hres); hres = NULL; } // if: error getting resource ClusterResourceCloseEnum(hresenum); delete [] pszName; delete [] pszResType; return bIsNetNameProvider; } //*** CIpAddrParamsPage::BIsNetNameProvider()