//+--------------------------------------------------------------------------- // // 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 = (INT)SendDlgItemMessage(CMB_NameService, CB_ADDSTRING, 0, (LPARAM)pszCBItem); SendDlgItemMessage(CMB_NameService, CB_SETITEMDATA, iItem, (LPARAM)pnspNT); pszCBItem = SzLoadIds(STR_DCELocator); iItem = (INT)SendDlgItemMessage(CMB_NameService, CB_ADDSTRING, 0, (LPARAM)pszCBItem); SendDlgItemMessage(CMB_NameService, CB_SETITEMDATA, iItem, (LPARAM)pnspDCE); cItems = (INT)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(lParam); Assert(lphi); if ((g_aHelpIDs_DLG_RPCConfig != NULL) && (HELPINFO_WINDOW == lphi->iContextType)) { ::WinHelp(static_cast(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 = (INT)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 = (INT)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 = (INT)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 = (INT)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; }