windows-nt/Source/XPSP1/NT/net/config/netcfg/msclicfg/rpcdlg.cpp
2020-09-26 16:20:57 +08:00

589 lines
16 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1997.
//
// File: R P C D L G . C P P
//
// Contents: Dialog box handling for RPC configuration.
//
// Notes:
//
// Author: danielwe 3 Mar 1997
//
//----------------------------------------------------------------------------
#include "pch.h"
#pragma hdrstop
#include "mscliobj.h"
#include "msclidlg.h"
#include "ncatlui.h"
#include "ncerror.h"
#include "ncreg.h"
#include "ncui.h"
#include "msclihlp.h"
//
// Name service provider struct. Just holds some data used by the dialog.
//
struct NSP
{
PCWSTR pszProtocol;
PCWSTR pszEndPoint;
WCHAR szNetAddr[c_cchMaxNetAddr];
BOOL fUsesNetAddr;
};
static const WCHAR c_szRegKeyNameSvc[] = L"Software\\Microsoft\\Rpc\\NameService";
static const WCHAR c_szNetAddress[] = L"NetworkAddress";
static const WCHAR c_szSrvNetAddress[] = L"ServerNetworkAddress";
static const WCHAR c_szProtocol[] = L"Protocol";
static const WCHAR c_szValueEndPoint[] = L"Endpoint";
static const WCHAR c_szProtDCE[] = L"ncacn_ip_tcp";
static const WCHAR c_szEndPoint[] = L"\\pipe\\locator";
// Used externally
extern const WCHAR c_szDefNetAddr[] = L"\\\\.";
extern const WCHAR c_szProtWinNT[] = L"ncacn_np";
// Helpfile
extern const WCHAR c_szNetCfgHelpFile[];
//+---------------------------------------------------------------------------
//
// Member: CMSClient::HrGetRPCRegistryInfo
//
// Purpose: Reads the current state of the RPC configuration from the
// registry into an in-memory struct. All changes occur to the
// struct until Apply() is called at which time all changes are
// written from the struct to the registry. Any values that
// cannot be obtained are given reasonable defaults.
//
// Arguments:
// (none)
//
// Returns: HRESULT, Error code.
//
// Author: danielwe 3 Mar 1997
//
// Notes:
//
HRESULT CMSClient::HrGetRPCRegistryInfo()
{
HRESULT hr = S_OK;
// This key *will* be there because it's in the system hive.
hr = HrRegOpenKeyBestAccess(HKEY_LOCAL_MACHINE, c_szRegKeyNameSvc,
&m_hkeyRPCName);
if (FAILED(hr))
{
goto err;
}
// Find out what protocol the current name service provider is using.
// This will allow us to set the default selection for the combo box.
hr = HrRegQueryString(m_hkeyRPCName, c_szProtocol,
&m_rpcData.strProt);
if (FAILED(hr))
{
goto err;
}
// Get the current value of the end point
hr = HrRegQueryString(m_hkeyRPCName, c_szValueEndPoint,
&m_rpcData.strEndPoint);
if (FAILED(hr))
{
if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
{
// Use default value
m_rpcData.strEndPoint = c_szEndPoint;
hr = S_OK;
}
else
{
goto err;
}
}
// If the name service provider uses a network address, we need to get it
// too so we can fill in that nice little edit box with it.
hr = HrRegQueryString(m_hkeyRPCName, c_szNetAddress,
&m_rpcData.strNetAddr);
if (FAILED(hr))
{
goto err;
}
err:
TraceError("CMSClient::HrGetRPCRegistryInfo", hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Member: CMSClient::HrSetRPCRegistryInfo
//
// Purpose: Write out changes to the data structure (if there were any) to
// the registry.
//
// Arguments:
// (none)
//
// Returns: HRESULT, Error code.
//
// Author: danielwe 3 Mar 1997
//
// Notes:
//
HRESULT CMSClient::HrSetRPCRegistryInfo()
{
HRESULT hr = S_OK;
struct REG_SET
{
PCWSTR pszValue;
const tstring * pstrData;
};
const REG_SET aregs[] =
{
{c_szNetAddress, &m_rpcData.strNetAddr},
{c_szSrvNetAddress, &m_rpcData.strNetAddr},
{c_szValueEndPoint, &m_rpcData.strEndPoint},
{c_szProtocol, &m_rpcData.strProt},
};
static const INT cregs = celems(aregs);
if (m_fRPCChanges)
{
INT iregs;
for (iregs = 0; iregs < cregs; iregs++)
{
Assert(aregs[iregs].pstrData);
hr = HrRegSetString(m_hkeyRPCName, aregs[iregs].pszValue,
*aregs[iregs].pstrData);
if (FAILED(hr))
{
goto err;
}
}
}
err:
TraceError("CMSClient::HrSetRPCRegistryInfo", hr);
return hr;
}
//
// Dialog handlers
//
//+---------------------------------------------------------------------------
//
// Member: CRPCConfigDlg::OnInitDialog
//
// Purpose: Called when this dialog is first brought up.
//
// Arguments:
// uMsg [in]
// wParam [in] See the ATL documentation for params.
// lParam [in]
// bHandled [in]
//
// Returns: See the ATL documentation for return results.
//
// Author: danielwe 3 Mar 1997
//
// Notes:
//
LRESULT CRPCConfigDlg::OnInitDialog(UINT uMsg, WPARAM wParam,
LPARAM lParam, BOOL& bHandled)
{
HRESULT hr = S_OK;
PCWSTR pszCBItem;
NSP * pnspNT = NULL;
NSP * pnspDCE = NULL;
INT iItem;
INT cItems;
const RPC_CONFIG_DATA * prpcData;
// Make sure selection is always undetermined when the dialog is invoked.
m_isel = -1;
prpcData = m_pmsc->RPCData();
Assert(prpcData);
// Allocate some structs to associate with item data.
pnspNT = new NSP;
pnspDCE = new NSP;
if ((pnspNT == NULL) ||
(pnspDCE == NULL))
{
return(E_OUTOFMEMORY);
}
pnspNT->pszProtocol = c_szProtWinNT;
pnspNT->pszEndPoint = c_szEndPoint;
// This field is unused by NT name service. Just zero it out. When it
// comes time to save the network address, we'll see that fUsesNetAddr is
// FALSE and the szNetAddr string is empty and just save a hardcoded
// net address.
*pnspNT->szNetAddr = 0;
pnspNT->fUsesNetAddr = FALSE;
pnspDCE->pszProtocol = c_szProtDCE;
pnspDCE->pszEndPoint = L"";
*pnspDCE->szNetAddr = 0;
pnspDCE->fUsesNetAddr = TRUE;
//
// Setup Name Service combo box
//
pszCBItem = SzLoadIds(STR_NTLocator);
iItem = SendDlgItemMessage(CMB_NameService, CB_ADDSTRING, 0,
(LPARAM)pszCBItem);
SendDlgItemMessage(CMB_NameService, CB_SETITEMDATA, iItem,
(LPARAM)pnspNT);
pszCBItem = SzLoadIds(STR_DCELocator);
iItem = SendDlgItemMessage(CMB_NameService, CB_ADDSTRING, 0,
(LPARAM)pszCBItem);
SendDlgItemMessage(CMB_NameService, CB_SETITEMDATA, iItem,
(LPARAM)pnspDCE);
cItems = SendDlgItemMessage(CMB_NameService, CB_GETCOUNT);
// Find the item in the list that has the same protocol as the one from
// the registry and make it the current selection.
for (iItem = 0; iItem < cItems; iItem++)
{
NSP *pnsp = (NSP *)SendDlgItemMessage(CMB_NameService,
CB_GETITEMDATA, iItem, 0);
Assert(pnsp);
if (!lstrcmpiW (pnsp->pszProtocol, prpcData->strProt.c_str()))
{
lstrcpyW (pnsp->szNetAddr, prpcData->strNetAddr.c_str());
SendDlgItemMessage (CMB_NameService, CB_SETCURSEL, iItem, 0);
break;
}
}
AssertSz(iItem != cItems, "Protocol not found!");
// Limit the edit box to the maximum length of a network address.
SendDlgItemMessage(EDT_NetAddress, EM_LIMITTEXT, c_cchMaxNetAddr, 0);
SetState();
TraceError("CRPCConfigDlg::OnInitDialog", hr);
return LresFromHr(hr);
}
//+---------------------------------------------------------------------------
//
// Method: CRPCConfigDlg::OnContextMenu
//
// Desc: Bring up context-sensitive help
//
// Args: Standard command parameters
//
// Return: LRESULT
//
LRESULT
CRPCConfigDlg::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& fHandled)
{
if (g_aHelpIDs_DLG_RPCConfig != NULL)
{
::WinHelp(m_hWnd,
c_szNetCfgHelpFile,
HELP_CONTEXTMENU,
(ULONG_PTR)g_aHelpIDs_DLG_RPCConfig);
}
return 0;
}
//+---------------------------------------------------------------------------
//
// Method: CRPCConfigDlg::OnHelp
//
// Desc: Bring up context-sensitive help when dragging ? icon over a control
//
// Args: Standard command parameters
//
// Return: LRESULT
//
//
LRESULT
CRPCConfigDlg::OnHelp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& fHandled)
{
LPHELPINFO lphi = reinterpret_cast<LPHELPINFO>(lParam);
Assert(lphi);
if ((g_aHelpIDs_DLG_RPCConfig != NULL) && (HELPINFO_WINDOW == lphi->iContextType))
{
::WinHelp(static_cast<HWND>(lphi->hItemHandle),
c_szNetCfgHelpFile,
HELP_WM_HELP,
(ULONG_PTR)g_aHelpIDs_DLG_RPCConfig);
}
return 0;
}
//+---------------------------------------------------------------------------
//
// Member: CRPCConfigDlg::SetState
//
// Purpose: Set the state of the edit control when selection changes.
//
// Arguments:
// (none)
//
// Returns: Nothing.
//
// Author: danielwe 3 Mar 1997
//
// Notes:
//
VOID CRPCConfigDlg::SetState()
{
INT iItem;
NSP * pnsp;
NSP * pnspOld = NULL;
HWND hwndEdit = GetDlgItem(EDT_NetAddress);
iItem = SendDlgItemMessage(CMB_NameService, CB_GETCURSEL, 0, 0);
Assert(iItem != CB_ERR);
// If the selection hasn't changed, just return
if (iItem == m_isel)
return;
if (m_isel != -1)
{
// Get the item data of the previous selection
pnspOld = (NSP *)SendDlgItemMessage(CMB_NameService,
CB_GETITEMDATA, m_isel, 0);
}
m_isel = iItem;
// Get the item data of the new selection
pnsp = (NSP *)SendDlgItemMessage(CMB_NameService,
CB_GETITEMDATA, iItem, 0);
Assert(pnsp);
if (pnsp->fUsesNetAddr)
{
// This provider uses the NetAddress field. Set the edit control with
// its text.
::SetWindowText(hwndEdit, pnsp->szNetAddr);
}
else
{
// Doesn't use NetAddress. Blank it out and save the old one.
if (pnspOld)
{
::GetWindowText(hwndEdit, pnspOld->szNetAddr, c_cchMaxNetAddr);
}
::SetWindowText(hwndEdit, L"");
}
// Disable the edit box for name service providers that don't use the
// network address field.
::EnableWindow(hwndEdit, pnsp->fUsesNetAddr);
::EnableWindow(GetDlgItem(IDC_TXT_NetAddress), pnsp->fUsesNetAddr);
}
//+---------------------------------------------------------------------------
//
// Member: CRPCConfigDlg::HrValidateRpcData
//
// Purpose: Ensures that the RPC data entered in the dialog is valid.
//
// Arguments:
// (none)
//
// Returns: S_OK, if no errors, or NETCFG_E_PSNRET_INVALID_NCPAGE if there
// were errors.
//
// Author: danielwe 21 Apr 1997
//
// Notes:
//
HRESULT CRPCConfigDlg::HrValidateRpcData()
{
HRESULT hr = S_OK;
INT iItem;
NSP * pnsp;
HWND hwndEdit = GetDlgItem(EDT_NetAddress);
iItem = SendDlgItemMessage(CMB_NameService, CB_GETCURSEL, 0, 0);
if (iItem != CB_ERR)
{
// Get current name service info.
pnsp = (NSP *)SendDlgItemMessage(CMB_NameService, CB_GETITEMDATA,
iItem, 0);
Assert(pnsp);
if (pnsp->fUsesNetAddr)
{
INT cch;
// This name service uses the network address field. Make sure it
// is not empty
cch = ::GetWindowTextLength(hwndEdit);
if (!cch)
{
// DCE doesn't allow empty network addresses
NcMsgBox(m_hWnd, STR_ErrorCaption, STR_InvalidNetAddress,
MB_OK | MB_ICONEXCLAMATION);
::SetFocus(hwndEdit);
hr = NETCFG_E_PSNRET_INVALID_NCPAGE;
}
}
}
TraceError("CRPCConfigDlg::HrValidateRpcData", hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Member: CRPCConfigDlg::OnKillActive
//
// Purpose: Called when the current page is switched away from or the
// property sheet is closed.
//
// Arguments:
// idCtrl []
// pnmh [] See the ATL documentation for return results.
// bHandled []
//
// Returns: S_OK, if no errors, or NETCFG_E_PSNRET_INVALID_NCPAGE if there
// were errors.
//
// Author: danielwe 21 Apr 1997
//
// Notes:
//
LRESULT CRPCConfigDlg::OnKillActive(int idCtrl, LPNMHDR pnmh, BOOL& bHandled)
{
HRESULT hr = S_OK;
hr = HrValidateRpcData();
TraceError("CRPCConfigDlg::OnKillActive", hr);
return LresFromHr(hr);
}
//+---------------------------------------------------------------------------
//
// Member: CRPCConfigDlg::OnOk
//
// Purpose: Called when the OK button is pressed.
//
// Arguments:
// idCtrl [in]
// pnmh [in] See the ATL documentation for params.
// bHandled [in]
//
// Returns: See the ATL documentation for return results.
//
// Author: danielwe 3 Mar 1997
//
// Notes:
//
LRESULT CRPCConfigDlg::OnOk(int idCtrl, LPNMHDR pnmh, BOOL& bHandled)
{
HRESULT hr = S_OK;
INT iItem;
NSP * pnsp;
HWND hwndEdit = GetDlgItem(EDT_NetAddress);
RPC_CONFIG_DATA * prpcData;
// Get a read-write version of the in-memory RPC data
prpcData = m_pmsc->RPCDataRW();
Assert(prpcData);
iItem = SendDlgItemMessage(CMB_NameService, CB_GETCURSEL, 0, 0);
Assert(iItem != CB_ERR);
pnsp = (NSP *)SendDlgItemMessage(CMB_NameService,
CB_GETITEMDATA, iItem, 0);
Assert(pnsp);
if (pnsp->fUsesNetAddr)
{
#ifdef DBG
INT cch;
cch = ::GetWindowTextLength(hwndEdit);
AssertSz(cch, "I though we validated this was not empty!");
#endif
// obtain network address from edit control
::GetWindowText(hwndEdit, pnsp->szNetAddr, c_cchMaxNetAddr);
}
else
{
// copy in a default network address
lstrcpyW (pnsp->szNetAddr, c_szDefNetAddr);
}
// Set the in-memory RPC data
prpcData->strNetAddr = pnsp->szNetAddr;
prpcData->strEndPoint = pnsp->pszEndPoint;
prpcData->strProt = pnsp->pszProtocol;
m_pmsc->SetRPCDirty();
TraceError("CRPCConfigDlg::OnOk", hr);
return LresFromHr(hr);
}
//+---------------------------------------------------------------------------
//
// Member: CRPCConfigDlg::OnDestroy
//
// Purpose: Called when the dialog is destroyed.
//
// Arguments:
// uMsg [in]
// wParam [in] See the ATL documentation for params.
// lParam [in]
// bHandled [in]
//
// Returns: See the ATL documentation for return results.
//
// Author: danielwe 3 Mar 1997
//
// Notes:
//
LRESULT CRPCConfigDlg::OnDestroy(UINT uMsg, WPARAM wParam,
LPARAM lParam, BOOL& bHandled)
{
INT iItem;
INT cItems;
NSP * pnsp;
// Walk the list of name service providers and free the NSP structs we
// allocated before.
cItems = SendDlgItemMessage(CMB_NameService, CB_GETCOUNT, 0, 0);
for (iItem = 0; iItem < cItems; iItem++)
{
pnsp = (NSP *)SendDlgItemMessage(CMB_NameService,
CB_GETITEMDATA, iItem, 0);
AssertSz(pnsp, "This should not be NULL!");
delete pnsp;
}
return 0;
}