/*++ Copyright(c) 1998,99 Microsoft Corporation Module Name: wlbs.cpp Abstract: Windows Load Balancing Service (WLBS) Notifier object - main module implementing object Author: kyrilf --*/ #include "pch.h" #pragma hdrstop #include "netcon.h" #include "ncatlui.h" #include "ndispnp.h" #include "ncsetup.h" #include "wlbs.h" #include "help.h" #include "tracelog.h" #include "wlbs.tmh" // for event tracing // ---------------------------------------------------------------------- // // Function: CWLBS::CWLBS // // Purpose: constructor for class CWLBS // // Arguments: None // // Returns: None // // Notes: // // ---------------------------------------------------------------------- CWLBS::CWLBS(VOID) { m_pClusterDlg = NULL; m_pHostDlg = NULL; m_pPortsDlg = NULL; ZeroMemory(&m_AdapterGuid, sizeof(m_AdapterGuid)); ZeroMemory(&m_OriginalConfig, sizeof(m_OriginalConfig)); ZeroMemory(&m_AdapterConfig, sizeof(m_AdapterConfig)); // // Register tracing // WPP_INIT_TRACING(L"Microsoft\\NLB"); } // ---------------------------------------------------------------------- // // Function: CWLBS::~CWLBS // // Purpose: destructor for class CWLBS // // Arguments: None // // Returns: None // // Notes: // // ---------------------------------------------------------------------- CWLBS::~CWLBS(VOID) { if (m_pClusterDlg != NULL) delete m_pClusterDlg; if (m_pHostDlg != NULL) delete m_pHostDlg; if (m_pPortsDlg != NULL) delete m_pPortsDlg; // // DeRegister tracing // WPP_CLEANUP();; } // ================================================================= // INetCfgNotify // // The following functions provide the INetCfgNotify interface // ================================================================= // ---------------------------------------------------------------------- // // Function: CWLBS::Initialize // // Purpose: Initialize the notify object // // Arguments: // pnccItem [in] pointer to INetCfgComponent object // pnc [in] pointer to INetCfg object // fInstalling [in] TRUE if we are being installed // // Returns: // // Notes: // // ---------------------------------------------------------------------- STDMETHODIMP CWLBS::Initialize(INetCfgComponent* pnccItem, INetCfg* pINetCfg, BOOL fInstalling) { TRACE_VERB("<->%!FUNC!"); return m_WlbsConfig.Initialize(pINetCfg, fInstalling); } // ---------------------------------------------------------------------- // // Function: CWLBS::ReadAnswerFile // // Purpose: Read settings from answerfile and configure WLBS // // Arguments: // pszAnswerFile [in] name of AnswerFile // pszAnswerSection [in] name of parameters section // // Returns: // // Notes: Dont do anything irreversible (like modifying registry) yet // since the config. actually complete only when Apply is called! // // ---------------------------------------------------------------------- STDMETHODIMP CWLBS::ReadAnswerFile(PCWSTR pszAnswerFile, PCWSTR pszAnswerSection) { TRACE_VERB("<->%!FUNC!"); return m_WlbsConfig.ReadAnswerFile(pszAnswerFile, pszAnswerSection); } // ---------------------------------------------------------------------- // // Function: CWLBS::Install // // Purpose: Do operations necessary for install. // // Arguments: // dwSetupFlags [in] Setup flags // // Returns: S_OK on success, otherwise an error code // // Notes: Dont do anything irreversible (like modifying registry) yet // since the config. actually complete only when Apply is called! // // ---------------------------------------------------------------------- STDMETHODIMP CWLBS::Install(DWORD dw) { TRACE_VERB("<->%!FUNC!"); return m_WlbsConfig.Install(dw); } // ---------------------------------------------------------------------- // // Function: CWLBS::Upgrade // // Purpose: Do operations necessary for upgrade. // // Arguments: // dwSetupFlags [in] Setup flags // // Returns: S_OK on success, otherwise an error code // // ---------------------------------------------------------------------- STDMETHODIMP CWLBS::Upgrade(DWORD dw1, DWORD dw2) { TRACE_VERB("<->%!FUNC!"); return m_WlbsConfig.Upgrade(dw1, dw2); } // ---------------------------------------------------------------------- // // Function: CWLBS::Removing // // Purpose: Do necessary cleanup when being removed // // Arguments: None // // Returns: S_OK on success, otherwise an error code // // Notes: Dont do anything irreversible (like modifying registry) yet // since the removal is actually complete only when Apply is called! // // ---------------------------------------------------------------------- STDMETHODIMP CWLBS::Removing(VOID) { TRACE_VERB("<->%!FUNC!"); return m_WlbsConfig.Removing(); } // ---------------------------------------------------------------------- // // Function: CWLBS::Validate // // Purpose: Do necessary parameter validation // // Arguments: None // // Returns: S_OK on success, otherwise an error code // // Notes: // // ---------------------------------------------------------------------- STDMETHODIMP CWLBS::Validate() { TRACE_VERB("<->%!FUNC!"); return S_OK; } // ---------------------------------------------------------------------- // // Function: CWLBS::Cancel // // Purpose: Cancel any changes made to internal data // // Arguments: None // // Returns: S_OK on success, otherwise an error code // // Notes: // // ---------------------------------------------------------------------- STDMETHODIMP CWLBS::CancelChanges(VOID) { TRACE_VERB("<->%!FUNC!"); return S_OK; } // ---------------------------------------------------------------------- // // Function: CWLBS::ApplyRegistryChanges // // Purpose: Apply changes. // // Arguments: None // // Returns: S_OK on success, otherwise an error code // // Notes: We can make changes to registry etc. here. // // ---------------------------------------------------------------------- STDMETHODIMP CWLBS::ApplyRegistryChanges(VOID) { TRACE_VERB("<->%!FUNC!"); return m_WlbsConfig.ApplyRegistryChanges(); } // ---------------------------------------------------------------------- // // Function: CWLBS::ApplyPnpChanges // // Purpose: Apply changes. // // Arguments: None // // Returns: S_OK on success, otherwise an error code // // Notes: Propagate changes to the driver. // // ---------------------------------------------------------------------- STDMETHODIMP CWLBS::ApplyPnpChanges(INetCfgPnpReconfigCallback* pICallback) { TRACE_VERB("<->%!FUNC!"); return m_WlbsConfig.ApplyPnpChanges(); } // ================================================================= // INetCfgBindNotify // ================================================================= // ---------------------------------------------------------------------- // // Function: CWLBS::QueryBindingPath // // Purpose: Allow or veto a binding path involving us // // Arguments: // dwChangeFlag [in] type of binding change // pncbi [in] pointer to INetCfgBindingPath object // // Returns: S_OK on success, otherwise an error code // // Notes: // // ---------------------------------------------------------------------- STDMETHODIMP CWLBS::QueryBindingPath(DWORD dwChangeFlag, INetCfgBindingPath* pncbp) { TRACE_VERB("->%!FUNC!"); INetCfgComponent* pAdapter = NULL; HRESULT hr = HrGetLastComponentAndInterface (pncbp, &pAdapter, NULL); if (SUCCEEDED(hr) && pAdapter) { TRACE_INFO("%!FUNC! get last component succeeded"); hr = m_WlbsConfig.QueryBindingPath(dwChangeFlag, pAdapter); pAdapter->Release(); if (FAILED(hr)) { TRACE_CRIT("%!FUNC! failed to query binding path with %d", hr); } else { TRACE_INFO("%!FUNC! query binding path succeeded"); } } else { TRACE_CRIT("%!FUNC! failed on get last component with %d", hr); } TRACE_VERB("<-%!FUNC!"); return hr; } // ---------------------------------------------------------------------- // // Function: CWLBS::NotifyBindingPath // // Purpose: System tells us by calling this function which // binding path involving us has just been formed. // // Arguments: // dwChangeFlag [in] type of binding change // pncbp [in] pointer to INetCfgBindingPath object // // Returns: S_OK on success, otherwise an error code // // Notes: // // ---------------------------------------------------------------------- STDMETHODIMP CWLBS::NotifyBindingPath(DWORD dwChangeFlag, INetCfgBindingPath* pncbp) { TRACE_VERB("<->%!FUNC!"); return m_WlbsConfig.NotifyBindingPath(dwChangeFlag, pncbp); } // ================================================================= // INetCfgProperties // ================================================================= // ---------------------------------------------------------------------- // // Function: CWLBS::SetContext // // Purpose: // // Arguments: // // Returns: // // Notes: // // ---------------------------------------------------------------------- STDMETHODIMP CWLBS::SetContext(IUnknown * pUnk) { TRACE_VERB("->%!FUNC!"); HRESULT hr = S_OK; if (pUnk) { INetLanConnectionUiInfo * pLanConnUiInfo; /* Set the new context. Here we assume that we are going to be called only for a LAN connection since the sample IM works only with LAN devices. */ hr = pUnk->QueryInterface(IID_INetLanConnectionUiInfo, reinterpret_cast(&pLanConnUiInfo)); if (SUCCEEDED(hr)) { hr = pLanConnUiInfo->GetDeviceGuid(&m_AdapterGuid); ReleaseObj(pLanConnUiInfo); TRACE_INFO("%!FUNC! query interface succeeded"); } else { TraceError("CWLBS::SetContext called for non-lan connection", hr); TRACE_INFO("%!FUNC! query interface failed with %d", hr); return hr; } } else { /* Clear context. */ ZeroMemory(&m_AdapterGuid, sizeof(m_AdapterGuid)); TRACE_INFO("%!FUNC! clearing context"); } /* If S_OK is not returned, the property page will not be displayed. */ TRACE_VERB("<-%!FUNC!"); return S_OK; } // ---------------------------------------------------------------------- // // Function: CWLBS::MergePropPages // // Purpose: Supply our property page to system // // Arguments: // pdwDefPages [out] pointer to num default pages // pahpspPrivate [out] pointer to array of pages // pcPages [out] pointer to num pages // hwndParent [in] handle of parent window // szStartPage [in] pointer to // // Returns: S_OK on success, otherwise an error code // // Notes: // // ---------------------------------------------------------------------- STDMETHODIMP CWLBS::MergePropPages(DWORD* pdwDefPages, LPBYTE* pahpspPrivate, UINT* pcPages, HWND hwndParent, PCWSTR* pszStartPage) { TRACE_VERB("->%!FUNC!"); HPROPSHEETPAGE * ahpsp = NULL; HRESULT hr = S_OK;; /* We don't want any default pages to be shown. */ *pdwDefPages = 0; *pcPages = 0; *pahpspPrivate = NULL; ahpsp = (HPROPSHEETPAGE*)CoTaskMemAlloc(3 * sizeof(HPROPSHEETPAGE)); if (m_pClusterDlg != NULL) { delete m_pClusterDlg; m_pClusterDlg = NULL; } if (m_pHostDlg != NULL) { delete m_pHostDlg; m_pHostDlg = NULL; } if (m_pPortsDlg != NULL) { delete m_pPortsDlg; m_pPortsDlg = NULL; } if (ahpsp) { /* Get the cached configuration. */ if (FAILED (hr = m_WlbsConfig.GetAdapterConfig(m_AdapterGuid, &m_OriginalConfig))) { TraceError("CWLBS::MergePropPages failed to query cluster config", hr); m_WlbsConfig.SetDefaults(&m_OriginalConfig); TRACE_CRIT("%!FUNC! failed in query to cluster configuration with %d", hr); } else { TRACE_INFO("%!FUNC! successfully retrieved the cached configuration"); } /* Copy the configuration into the "current" config. */ CopyMemory(&m_AdapterConfig, &m_OriginalConfig, sizeof(m_OriginalConfig)); m_pClusterDlg = new CDialogCluster(&m_AdapterConfig, g_aHelpIDs_IDD_DIALOG_CLUSTER); if (NULL == m_pClusterDlg) { TRACE_CRIT("%!FUNC! memory allocation failure for cluster page dialog"); } ahpsp[0] = m_pClusterDlg->CreatePage(IDD_DIALOG_CLUSTER, 0); m_pHostDlg = new CDialogHost(&m_AdapterConfig, g_aHelpIDs_IDD_DIALOG_HOST); if (NULL == m_pHostDlg) { TRACE_CRIT("%!FUNC! memory allocation failure for host page dialog"); } ahpsp[1] = m_pHostDlg->CreatePage(IDD_DIALOG_HOST, 0); m_pPortsDlg = new CDialogPorts(&m_AdapterConfig, g_aHelpIDs_IDD_DIALOG_PORTS); if (NULL == m_pPortsDlg) { TRACE_CRIT("%!FUNC! memory allocation failure for ports page dialog"); } ahpsp[2] = m_pPortsDlg->CreatePage(IDD_DIALOG_PORTS, 0); *pcPages = 3; *pahpspPrivate = (LPBYTE)ahpsp; } else { TRACE_CRIT("%!FUNC! CoTaskMemAlloc failed"); } TRACE_VERB("<-%!FUNC!"); return S_OK; } // ---------------------------------------------------------------------- // // Function: CWLBS::ValidateProperties // // Purpose: Validate changes to property page // // Arguments: // hwndSheet [in] window handle of property sheet // // Returns: S_OK on success, otherwise an error code // // Notes: // // ---------------------------------------------------------------------- STDMETHODIMP CWLBS::ValidateProperties(HWND hwndSheet) { TRACE_VERB("->%!FUNC!"); NETCFG_WLBS_CONFIG adapterConfig; /* Make a copy of our config. It is voodoo to pass a pointer to a private date member, so we make a copy instead. */ CopyMemory(&adapterConfig, &m_AdapterConfig, sizeof(m_AdapterConfig)); TRACE_VERB("<-%!FUNC!"); return m_WlbsConfig.ValidateProperties(hwndSheet, m_AdapterGuid, &adapterConfig); } // ---------------------------------------------------------------------- // // Function: CWLBS::CancelProperties // // Purpose: Cancel changes to property page // // Arguments: None // // Returns: S_OK on success, otherwise an error code // // Notes: // // ---------------------------------------------------------------------- STDMETHODIMP CWLBS::CancelProperties(VOID) { TRACE_VERB("->%!FUNC!"); delete m_pClusterDlg; delete m_pHostDlg; delete m_pPortsDlg; m_pClusterDlg = NULL; m_pHostDlg = NULL; m_pPortsDlg = NULL; TRACE_VERB("<-%!FUNC!"); return S_OK; } // ---------------------------------------------------------------------- // // Function: CWLBS::ApplyProperties // // Purpose: Apply value of controls on property page // to internal memory structure // // Arguments: None // // Returns: S_OK on success, otherwise an error code // // Notes: We do this work in OnOk so no need to do it here again. // // ---------------------------------------------------------------------- STDMETHODIMP CWLBS::ApplyProperties(VOID) { TRACE_VERB("->%!FUNC!"); /* If the cluster IP address / subnet mask or the dedicated IP address / subnet mask has changed in this configuration session, remind the user that they have to enter this address in TCP/IP properties as well. */ if (wcscmp(m_OriginalConfig.cl_ip_addr, m_AdapterConfig.cl_ip_addr) || wcscmp(m_OriginalConfig.cl_net_mask, m_AdapterConfig.cl_net_mask) || wcscmp(m_OriginalConfig.ded_ip_addr, m_AdapterConfig.ded_ip_addr) || wcscmp(m_OriginalConfig.ded_net_mask, m_AdapterConfig.ded_net_mask)) { /* Alert the user. */ NcMsgBox(::GetActiveWindow(), IDS_PARM_INFORMATION, IDS_PARM_TCPIP, MB_APPLMODAL | MB_ICONINFORMATION | MB_OK); TRACE_INFO("%!FUNC! vip and/or dip ip settings were modified"); } /* Commit the configuration. */ DWORD dwStatus = m_WlbsConfig.SetAdapterConfig(m_AdapterGuid, &m_AdapterConfig); if (S_OK != dwStatus) { TRACE_CRIT("%!FUNC! call to set the adapter configuration failed with %d", dwStatus); } else { TRACE_INFO("%!FUNC! call to set the adapter configuration succeeded"); } delete m_pClusterDlg; delete m_pHostDlg; delete m_pPortsDlg; m_pClusterDlg = NULL; m_pHostDlg = NULL; m_pPortsDlg = NULL; TRACE_VERB("<-%!FUNC!"); return S_OK; }