// 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); } } }