windows-nt/Source/XPSP1/NT/net/rras/ras/ui/rasdlg/penettab.c
2020-09-26 16:20:57 +08:00

835 lines
25 KiB
C

// Copyright (c) 1995, Microsoft Corporation, all rights reserved
//
// penettab.c
// Remote Access Common Dialog APIs
// Phonebook Entry property sheet (Networking tab)
//
// 12/10/97 Shaun Cox
//
#include "rasdlgp.h"
#include "entryps.h"
#include "inetcfgp.h"
#include "initguid.h"
#include "netcfgp.h"
#include "netconp.h"
#include "devguid.h"
#include "uiinfo.h"
typedef struct
_MAP_SZ_DWORD
{
LPCTSTR pszValue;
DWORD dwValue;
}
MAP_SZ_DWORD;
//For whistler bug#194394
//For 64bit, IPX wont show up
//For 32/64 bit, NETBEUI wont show up
//
#ifdef _WIN64
static const MAP_SZ_DWORD c_mapProtocols [] =
{
{ NETCFG_TRANS_CID_MS_TCPIP, NP_Ip },
{ NETCFG_TRANS_CID_MS_NETMON, NP_Netmon },
};
#else
static const MAP_SZ_DWORD c_mapProtocols [] =
{
{ NETCFG_TRANS_CID_MS_TCPIP, NP_Ip },
{ NETCFG_TRANS_CID_MS_NWIPX, NP_Ipx },
{ NETCFG_TRANS_CID_MS_NETMON, NP_Netmon },
};
#endif
//+---------------------------------------------------------------------------
//
// Function: DwProtocolFromComponentId
//
// Purpose: Return the DWORD value of the protocol corresponding to
// the string value in c_mapProtocols.
//
// Arguments:
// pszComponentId [in] Component id to find.
//
// Returns: NP_xxx value
//
// Author: shaunco 13 Dec 1997
//
// Notes: The input argument must exist in c_mapProtocols.
//
DWORD
DwProtocolFromComponentId (
LPCTSTR pszComponentId)
{
int i;
for (i = 0; i < sizeof(c_mapProtocols) / sizeof(c_mapProtocols[0]); i++)
{
if (0 == lstrcmpi (pszComponentId, c_mapProtocols[i].pszValue))
{
return c_mapProtocols[i].dwValue;
}
}
// Should never get here as we should never pass a protocol that is not
// in c_mapProtocols.
//
ASSERT (FALSE);
return 0;
}
//+---------------------------------------------------------------------------
//
// Function: GetComponentImageIndex
//
// Purpose: Returns the index into pcild corresponding to the class of
// pComponent.
//
// Arguments:
// pComponent [in] Component who's class should be used.
// pcild [in] Returned from SetupDiGetClassImageList
//
// Returns: A valid index or zero (which may also be valid).
//
// Author: shaunco 12 Dec 1997
//
// Notes:
//
int
GetComponentImageIndex (
INetCfgComponent* pComponent,
SP_CLASSIMAGELIST_DATA* pcild)
{
int iImage = 0;
GUID guidClass;
HRESULT hr = INetCfgComponent_GetClassGuid (pComponent, &guidClass);
if (SUCCEEDED(hr))
{
SetupDiGetClassImageIndex (pcild, &guidClass, &iImage);
}
return iImage;
}
//+---------------------------------------------------------------------------
//
// Function: HrEnumComponentsForListView
//
// Purpose: Return an array of INetCfgComponents that are candidates
// for adding to our list view. This is composed of all
// clients and servcies, and a few select protocols. (No
// net adapters.) Hidden components could be returned and
// should be checked before adding to the list view.
//
// Arguments:
// pNetCfg [in]
// celt [in]
// rgelt [out]
// pceltFetched [out]
//
// Returns: S_OK or an error.
//
// Author: shaunco 12 Dec 1997
//
// Notes:
//
HRESULT
HrEnumComponentsForListView (
INetCfg* pNetCfg,
ULONG celt,
INetCfgComponent** rgelt,
ULONG* pceltFetched)
{
static const GUID* c_apguidClasses [] =
{
&GUID_DEVCLASS_NETCLIENT,
&GUID_DEVCLASS_NETSERVICE,
};
HRESULT hr;
int i;
ULONG celtFetched = 0;
// Initialize the output parameters.
//
ZeroMemory (rgelt, celt * sizeof (*rgelt));
*pceltFetched = 0;
// Enumerate the clients and services.
//
hr = HrEnumComponentsInClasses (pNetCfg,
sizeof(c_apguidClasses) / sizeof(c_apguidClasses[0]),
(GUID**)c_apguidClasses,
celt, rgelt, &celtFetched);
// Find the protocols if they are installed.
//
for (i = 0; i < sizeof(c_mapProtocols) / sizeof(c_mapProtocols[0]); i++)
{
INetCfgComponent* pComponent;
hr = INetCfg_FindComponent (pNetCfg, c_mapProtocols[i].pszValue,
&pComponent);
if (S_OK == hr)
{
rgelt [celtFetched++] = pComponent;
}
}
*pceltFetched = celtFetched;
return S_OK;
}
//+---------------------------------------------------------------------------
//
// Function: HrNeRefreshListView
//
// Purpose: Clear and re-add all of the items that belong in the list
// view.
//
// Arguments:
// pInfo [in]
//
// Returns: S_OK or an error code.
//
// Author: shaunco 12 Dec 1997
//
// Notes:
//
HRESULT
HrNeRefreshListView (
PEINFO* pInfo)
{
HRESULT hr = S_OK;
INetCfgComponent* aComponents [256];
ULONG cComponents;
HIMAGELIST himlSmall;
PBENTRY* pEntry = pInfo->pArgs->pEntry;
PBFILE* pFile = pInfo->pArgs->pFile;
// Delete all existing items. The LVN_DELETEITEM handler is expected to
// release the objects we have attached prior.
//
ListView_DeleteAllItems (pInfo->hwndLvComponents);
hr = HrEnumComponentsForListView (pInfo->pNetCfg,
sizeof(aComponents)/sizeof(aComponents[0]),
aComponents, &cComponents);
if (SUCCEEDED(hr))
{
BOOL fHasPermission = TRUE;
ULONG i;
// check if user has any permission to change the bindings
INetConnectionUiUtilities * pncuu = NULL;
hr = HrCreateNetConnectionUtilities(&pncuu);
if (SUCCEEDED(hr))
{
fHasPermission =
INetConnectionUiUtilities_UserHasPermission(
pncuu, NCPERM_ChangeBindState);
INetConnectionUiUtilities_Release(pncuu);
}
for (i = 0; i < cComponents; i++)
{
INetCfgComponent* pComponent = aComponents [i];
DWORD dwCharacter;
LPWSTR pszwName = NULL;
LPWSTR pszwId = NULL;
int iItem;
LV_ITEM item = {0};
BOOL fCheck, fForceCheck = FALSE;
GUID guid;
BOOL fDisableCheckbox = FALSE;
// We'll release it if inserting it failed or we decided to
// skip it. By not releasing it, we pass ownership to the
// list view.
//
BOOL fReleaseComponent = TRUE;
// Don't add hidden components. Silently skip components
// that we fail to get the class GUID or display name for.
// (After all, what could we have the user do to fix the error?
// Might as well show them what we can.)
//
if ( FAILED(INetCfgComponent_GetCharacteristics (pComponent, &dwCharacter))
|| (dwCharacter & NCF_HIDDEN)
|| FAILED(INetCfgComponent_GetDisplayName (pComponent, &pszwName)))
{
goto skip_component;
}
//for whistler bug 29356 filter out Network Load Balancing
//
if (SUCCEEDED(INetCfgComponent_GetId(pComponent, &pszwId)))
{
WCHAR * pszwTmpId = NULL;
pszwTmpId = StrDupWFromT(NETCFG_SERVICE_CID_MS_WLBS);
if(pszwTmpId)
{
if ( 0 == lstrcmpW(pszwId, pszwTmpId))
{
Free0(pszwTmpId);
CoTaskMemFree (pszwId);
goto skip_component;
}
Free0(pszwTmpId);
}
CoTaskMemFree (pszwId);
}
// Disable the checkbox on components whose bindings are not user adjustable
// or user has no permission to adjust binding
if (NCF_FIXED_BINDING & dwCharacter)
{
fDisableCheckbox = TRUE;
}
// Bug #157213: Don't add any protocols other than IP if SLIP
// is enabled
//
// Bug #294401: Also filter out CSNW when server type is SLIP
if (pInfo->pArgs->pEntry->dwBaseProtocol == BP_Slip)
{
if (SUCCEEDED(INetCfgComponent_GetClassGuid(pComponent, &guid)))
{
BOOL fSkip = FALSE;
if (IsEqualGUID(&guid, &GUID_DEVCLASS_NETTRANS))
{
if (SUCCEEDED(INetCfgComponent_GetId(pComponent, &pszwId)))
{
if (DwProtocolFromComponentId(pszwId) == NP_Ip)
{
// This item is IP. We should disable the check
// box so the user can't disable TCP/IP in SLIP
// mode. This is done after the item is inserted.
//
fDisableCheckbox = TRUE;
// 122024
//
// We should also force the ui to show ip as enabled
// since IP is always used with SLIP.
//
fForceCheck = TRUE;
}
else
{
fSkip = TRUE;
}
CoTaskMemFree (pszwId);
}
}
else if (IsEqualGUID(&guid, &GUID_DEVCLASS_NETCLIENT))
{
if (SUCCEEDED(INetCfgComponent_GetId(pComponent, &pszwId)))
{
if (0 == lstrcmpi (pszwId, TEXT("MS_NWCLIENT")))
{
fSkip = TRUE;
}
CoTaskMemFree (pszwId);
}
}
if (fSkip)
{
goto skip_component;
}
}
}
// pmay: 348623
//
// If we are remote admining a router, only allow tcpip and
// ipx to be displayed.
//
if (pInfo->pArgs->fRouter && pInfo->pArgs->fRemote)
{
if (SUCCEEDED(INetCfgComponent_GetClassGuid(pComponent, &guid)))
{
BOOL fSkip = TRUE;
DWORD dwId;
if (IsEqualGUID(&guid, &GUID_DEVCLASS_NETTRANS))
{
if (SUCCEEDED(INetCfgComponent_GetId(pComponent, &pszwId)))
{
dwId = DwProtocolFromComponentId(pszwId);
if ((dwId == NP_Ip) || (dwId == NP_Ipx))
{
fSkip = FALSE;
}
CoTaskMemFree (pszwId);
}
}
if (fSkip)
{
goto skip_component;
}
}
}
item.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
item.pszText = pszwName;
item.iImage = GetComponentImageIndex (pComponent, &pInfo->cild);
item.lParam = (LPARAM)pComponent;
// Add the item.
//
iItem = ListView_InsertItem (pInfo->hwndLvComponents, &item);
if (-1 != iItem)
{
// List view now has it. We can't release it.
//
fReleaseComponent = FALSE;
// Set its check state.
//
if (! fForceCheck)
{
fCheck = NeIsComponentEnabled (pInfo, pComponent);
}
else
{
fCheck = TRUE;
}
ListView_SetCheck (pInfo->hwndLvComponents, iItem, fCheck);
// Disable the checkbox if this is psched. We don't allow
// users to change check state of psched from ras connections.
// bug 255749 [raos].
//
if(SUCCEEDED(INetCfgComponent_GetId(pComponent, &pszwId)))
{
// Check to see if this is psched.
//
if( (0 == _wcsicmp(pszwId, L"ms_psched"))
|| (0 == _wcsicmp(pszwId, L"ms_NetMon")))
{
fDisableCheckbox = TRUE;
}
}
if (fDisableCheckbox)
{
ListView_DisableCheck(pInfo->hwndLvComponents, iItem);
}
}
skip_component:
if (fReleaseComponent)
{
ReleaseObj (pComponent);
}
CoTaskMemFree (pszwName);
}
// Select first item
ListView_SetItemState(pInfo->hwndLvComponents, 0,
LVIS_SELECTED | LVIS_FOCUSED,
LVIS_SELECTED | LVIS_FOCUSED);
}
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: PComponentFromItemIndex
//
// Purpose: Return the INetCfgComponent associated with the specified
// list view item.
//
// Arguments:
// hwndLv [in]
// iItem [in]
//
// Returns: A (non-AddRef'd) copy of the INetCfgComponent pointer
// associated with the item.
//
// Author: shaunco 14 Dec 1997
//
// Notes: The returned value is NOT AddRef'd.
//
INetCfgComponent*
PComponentFromItemIndex (
HWND hwndLv,
int iItem)
{
INetCfgComponent* pComponent = NULL;
LV_ITEM item = {0};
item.mask = LVIF_PARAM;
item.iItem = iItem;
if (ListView_GetItem (hwndLv, &item))
{
pComponent = (INetCfgComponent*)item.lParam;
ASSERT (pComponent);
}
return pComponent;
}
//+---------------------------------------------------------------------------
//
// Function: PComponentFromCurSel
//
// Purpose:
//
// Arguments:
// hwndLv [in] Window handle of list view
// piItem [out] Optional address of integer to receive selected item.
//
// Returns:
//
// Author: shaunco 30 Dec 1997
//
// Notes:
//
INetCfgComponent*
PComponentFromCurSel (
HWND hwndLv,
int* piItem)
{
INetCfgComponent* pComponent = NULL;
// Get the current selection if it exists.
//
int iItem = ListView_GetNextItem (hwndLv, -1, LVNI_SELECTED);
if (-1 != iItem)
{
// Get the component associated with the current selection. It must
// exist.
//
pComponent = PComponentFromItemIndex (hwndLv, iItem);
ASSERT (pComponent);
}
// Return the index of the item if requested.
//
if (piItem)
{
*piItem = iItem;
}
return pComponent;
}
//+---------------------------------------------------------------------------
//
// Function: PeQueryOrChangeComponentEnabled
//
// Purpose:
//
// Arguments:
// pInfo []
// pComponent []
// fChange []
// fNewValue []
//
// Returns:
//
// Author: shaunco 14 Dec 1997
//
// Notes:
//
BOOL
NeQueryOrChangeComponentEnabled (
PEINFO* pInfo,
INetCfgComponent* pComponent,
BOOL fChange,
BOOL fValue)
{
BOOL fOldValue;
GUID guidClass;
HRESULT hr;
hr = INetCfgComponent_GetClassGuid (pComponent, &guidClass);
if (SUCCEEDED(hr))
{
LPWSTR pszwId;
hr = INetCfgComponent_GetId (pComponent, &pszwId);
if (SUCCEEDED(hr))
{
// We handle protocols in a hard-coded (er, well known) fashion.
//
if (IsEqualGUID (&guidClass, &GUID_DEVCLASS_NETTRANS))
{
DWORD* pdwValue = &pInfo->pArgs->pEntry->dwfExcludedProtocols;
// Check if the protocol is exluded.
//
DWORD dwProtocol = DwProtocolFromComponentId (pszwId);
if (fChange)
{
if (fValue)
{
// Include the protocol. (By not explicitly excluding
// it.
//
*pdwValue &= ~dwProtocol;
}
else
{
// Exclude the protocol. (Remember, its a list of
// excluded protocols.
//
*pdwValue |= dwProtocol;
}
}
else
{
fValue = !(dwProtocol & *pdwValue);
}
}
else
{
if (fChange)
{
EnableOrDisableNetComponent (pInfo->pArgs->pEntry,
pszwId, fValue);
}
else
{
// Default to enabled for the case whenthe value isn't
// found in the entry. This will be the case for pre-NT5
// entries and entries that have not yet been to the
// Networking tab for edits.
//
BOOL fEnabled;
fValue = TRUE;
if (FIsNetComponentListed(pInfo->pArgs->pEntry,
pszwId, &fEnabled, NULL))
{
fValue = fEnabled;
}
}
}
CoTaskMemFree (pszwId);
}
}
return fValue;
}
VOID
NeEnableComponent (
PEINFO* pInfo,
INetCfgComponent* pComponent,
BOOL fEnable)
{
NeQueryOrChangeComponentEnabled (pInfo, pComponent, TRUE, fEnable);
}
BOOL
NeIsComponentEnabled (
PEINFO* pInfo,
INetCfgComponent* pComponent)
{
return NeQueryOrChangeComponentEnabled (pInfo, pComponent, FALSE, FALSE);
}
VOID
NeShowComponentProperties (
IN PEINFO* pInfo)
{
HRESULT hr;
// Get the component for the current selection.
//
INetCfgComponent* pComponent;
pComponent = PComponentFromCurSel (pInfo->hwndLvComponents, NULL);
ASSERT (pComponent);
if(NULL == pComponent)
{
return;
}
// Create the UI info callback object if we haven't done so yet.
// If this fails, we can still show properties. TCP/IP just might
// not know which UI-variant to show.
//
if (!pInfo->punkUiInfoCallback)
{
HrCreateUiInfoCallbackObject (pInfo, &pInfo->punkUiInfoCallback);
}
// Show the component's property UI. If S_OK is returned, it means
// something changed.
//
hr = INetCfgComponent_RaisePropertyUi (pComponent,
pInfo->hwndDlg,
NCRP_SHOW_PROPERTY_UI,
pInfo->punkUiInfoCallback);
if (S_OK == hr)
{
// Get the INetCfgComponentPrivate interface so we can query the
// notify object directly.
//
INetCfgComponentPrivate* pPrivate;
hr = INetCfgComponent_QueryInterface (pComponent,
&IID_INetCfgComponentPrivate,
(VOID**)&pPrivate);
if (SUCCEEDED(hr))
{
// Get the INetRasConnectionIpUiInfo interface from the notify
// object.
//
INetRasConnectionIpUiInfo* pIpUiInfo;
hr = INetCfgComponentPrivate_QueryNotifyObject (pPrivate,
&IID_INetRasConnectionIpUiInfo,
(VOID**)&pIpUiInfo);
if (SUCCEEDED(hr))
{
// Get the UI info from TCP/IP.
//
RASCON_IPUI info;
hr = INetRasConnectionIpUiInfo_GetUiInfo (pIpUiInfo, &info);
if (SUCCEEDED(hr))
{
PBENTRY* pEntry = pInfo->pArgs->pEntry;
// Get rid of our current data before we copy the new
// data.
//
pEntry->dwIpAddressSource = ASRC_ServerAssigned;
pEntry->dwIpNameSource = ASRC_ServerAssigned;
Free0 (pEntry->pszIpAddress);
pEntry->pszIpAddress = NULL;
Free0 (pEntry->pszIpDnsAddress);
pEntry->pszIpDnsAddress = NULL;
Free0 (pEntry->pszIpDns2Address);
pEntry->pszIpDns2Address = NULL;
Free0 (pEntry->pszIpWinsAddress);
pEntry->pszIpWinsAddress = NULL;
Free0 (pEntry->pszIpWins2Address);
pEntry->pszIpWins2Address = NULL;
Free0 (pEntry->pszIpDnsSuffix);
pEntry->pszIpDnsSuffix = StrDup (info.pszwDnsSuffix);
if ((info.dwFlags & RCUIF_USE_IP_ADDR) &&
*info.pszwIpAddr)
{
pEntry->dwIpAddressSource = ASRC_RequireSpecific;
pEntry->pszIpAddress = StrDup (info.pszwIpAddr);
}
else
{
pEntry->dwIpAddressSource = ASRC_ServerAssigned;
Free0 (pEntry->pszIpAddress);
pEntry->pszIpAddress = NULL;
}
if (info.dwFlags & RCUIF_USE_NAME_SERVERS)
{
if (*info.pszwDnsAddr)
{
pEntry->dwIpNameSource = ASRC_RequireSpecific;
pEntry->pszIpDnsAddress = StrDup (info.pszwDnsAddr);
}
if (*info.pszwDns2Addr)
{
pEntry->dwIpNameSource = ASRC_RequireSpecific;
pEntry->pszIpDns2Address = StrDup (info.pszwDns2Addr);
}
if (*info.pszwWinsAddr)
{
pEntry->dwIpNameSource = ASRC_RequireSpecific;
pEntry->pszIpWinsAddress = StrDup (info.pszwWinsAddr);
}
if (*info.pszwWins2Addr)
{
pEntry->dwIpNameSource = ASRC_RequireSpecific;
pEntry->pszIpWins2Address = StrDup (info.pszwWins2Addr);
}
}
// pmay: 389632
//
// Use this convoluted logic to store something reasonable
// about the registration process.
//
if (info.dwFlags & RCUIF_USE_DISABLE_REGISTER_DNS)
{
pEntry->dwIpDnsFlags = 0;
}
else
{
BOOL bSuffix =
((pEntry->pszIpDnsSuffix) && (*(pEntry->pszIpDnsSuffix)));
pEntry->dwIpDnsFlags = DNS_RegPrimary;
if (info.dwFlags & RCUIF_USE_PRIVATE_DNS_SUFFIX)
{
if (bSuffix)
{
pEntry->dwIpDnsFlags |= DNS_RegPerConnection;
}
else
{
pEntry->dwIpDnsFlags |= DNS_RegDhcpInform;
}
}
}
// 277478
// Enable the NBT over IP controls
//
if (info.dwFlags & RCUIF_ENABLE_NBT)
{
pEntry->dwIpNbtFlags = PBK_ENTRY_IP_NBT_Enable;
}
else
{
pEntry->dwIpNbtFlags = 0;
}
if (pInfo->pArgs->fRouter)
{
pEntry->fIpPrioritizeRemote = FALSE;
}
else
{
pEntry->fIpPrioritizeRemote = info.dwFlags & RCUIF_USE_REMOTE_GATEWAY;
}
pEntry->fIpHeaderCompression = info.dwFlags & RCUIF_USE_HEADER_COMPRESSION;
pEntry->dwFrameSize = info.dwFrameSize;
}
ReleaseObj (pIpUiInfo);
}
ReleaseObj (pPrivate);
}
}
}