|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1997 - 2001.
//
// File: R A S C O N O B . C P P
//
// Contents: Implements the base class used to implement the Dialup,
// Direct, and Vpn connection objects. Also includes
// RAS-related utility functions used only within netman.exe.
//
// Notes:
//
// Author: shaunco 23 Sep 1997
//
//----------------------------------------------------------------------------
#include "pch.h"
#pragma hdrstop
#include "nmbase.h"
#include "nccom.h"
#include "ncperms.h"
#include "ncras.h"
#include "rasconob.h"
#include <raserror.h>
#include "gpnla.h"
extern CGroupPolicyNetworkLocationAwareness* g_pGPNLA;
//+---------------------------------------------------------------------------
//
// Member: CRasConnectionBase::CacheProperties
//
// Purpose:
//
// Arguments:
//
// Returns: nothing.
//
// Author: shaunco 2 Feb 1998
//
// Notes:
//
VOID CRasConnectionBase::CacheProperties ( IN const RASENUMENTRYDETAILS* pDetails) throw() { Assert (pDetails); AssertSz(pDetails->dwSize >= sizeof(RASENUMENTRYDETAILS), "RASENUMENTRYDETAILS too small");
m_fEntryPropertiesCached = TRUE; m_lRasEntryModifiedVersionEra = g_lRasEntryModifiedVersionEra;
m_guidId = pDetails->guidId; SetEntryName (pDetails->szEntryName); m_fForAllUsers = !!(pDetails->dwFlags & REN_AllUsers); m_fShowMonitorIconInTaskBar = pDetails->fShowMonitorIconInTaskBar; m_strDeviceName = pDetails->szDeviceName; m_dwFlagsPriv = pDetails->dwFlagsPriv; m_strPhoneNumber = pDetails->szPhoneNumber;
TraceTag(ttidWanCon, "PhoneNumber: %S", m_strPhoneNumber.c_str());
m_fBranded = (RASET_Internet == pDetails->dwType);
TraceTag (ttidWanCon, "rdt:0x%08x, dwType:0x%08x", pDetails->rdt, pDetails->dwType);
switch (LOWORD(pDetails->rdt)) { case RDT_PPPoE: m_MediaType = NCM_PPPOE; break;
case RDT_Modem: case RDT_X25: m_MediaType = NCM_PHONE; break;
case RDT_Isdn: m_MediaType = NCM_ISDN; break;
case RDT_Serial: case RDT_FrameRelay: case RDT_Atm: case RDT_Sonet: case RDT_Sw56: m_MediaType = NCM_PHONE; break;
case RDT_Tunnel_Pptp: case RDT_Tunnel_L2tp: m_MediaType = NCM_TUNNEL; break;
case RDT_Irda: case RDT_Parallel: m_MediaType = NCM_DIRECT; break;
case RDT_Other: default: if (RASET_Vpn == pDetails->dwType) { m_MediaType = NCM_TUNNEL; } else if (RASET_Direct == pDetails->dwType) { m_MediaType = NCM_DIRECT; } else { m_MediaType = NCM_PHONE; } break; }
if (pDetails->rdt & RDT_Tunnel) { m_MediaType = NCM_TUNNEL; } else if (pDetails->rdt & (RDT_Direct | RDT_Null_Modem)) { m_MediaType = NCM_DIRECT; } }
//+---------------------------------------------------------------------------
//
// Member: CRasConnectionBase::FAllowRemoval
//
// Purpose: Returns TRUE if the connection is in a state where we
// can validly remove it.
//
// Arguments:
// phrReason [out] If FALSE is returned, this is the reason. It is
// either E_ACCESSDENIED or E_UNEXPECTED.
//
// Returns: TRUE or FALSE.
//
// Author: shaunco 17 Jul 1998
//
// Notes:
//
BOOL CRasConnectionBase::FAllowRemoval ( OUT HRESULT* phrReason) throw() { Assert (phrReason); Assert (m_fEntryPropertiesCached);
// If this connection is for all users, the user must be
// an administrator or power user.
//
if (m_fForAllUsers && !FIsUserAdmin()) { *phrReason = E_ACCESSDENIED; return FALSE; }
// $$NOTE (jeffspr) -- moved the test for connection state to the
// delete function because we don't want it to affect our loading
// of characteristics
//
// If we passed all tests above, we're okay to remove.
//
*phrReason = S_OK; return TRUE; }
//+---------------------------------------------------------------------------
//
// Member: CRasConnectionBase::HrGetCharacteristics
//
// Purpose: Get the characteristics of the connection.
//
// Arguments:
// pdwFlags [out]
//
// Returns: S_OK or an error code
//
// Author: shaunco 17 Jul 1998
//
// Notes:
//
HRESULT CRasConnectionBase::HrGetCharacteristics ( OUT DWORD* pdwFlags) { Assert (pdwFlags);
DWORD dwFlags = NCCF_OUTGOING_ONLY;
HRESULT hr = HrEnsureEntryPropertiesCached (); if (SUCCEEDED(hr)) { if (FIsBranded ()) { dwFlags |= NCCF_BRANDED; } else { dwFlags |= (NCCF_ALLOW_RENAME | NCCF_ALLOW_DUPLICATION); }
if (m_fForAllUsers) { dwFlags |= NCCF_ALL_USERS; }
if (m_dwFlagsPriv & REED_F_Default) { dwFlags |= NCCF_DEFAULT; }
HRESULT hrReason; if (FAllowRemoval (&hrReason)) { dwFlags |= NCCF_ALLOW_REMOVAL; }
if (FShowIcon ()) { dwFlags |= NCCF_SHOW_ICON; }
if (S_OK == HrEnsureHNetPropertiesCached()) { if (m_HNetProperties.fIcsPublic) { dwFlags |= NCCF_SHARED; } BOOL fIsFirewalled = FALSE; hr = HrIsConnectionFirewalled(&fIsFirewalled); if (fIsFirewalled) { dwFlags |= NCCF_FIREWALLED; }
} }
*pdwFlags = dwFlags;
TraceError ("CRasConnectionBase::HrGetCharacteristics", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Member: CRasConnectionBase::HrGetStatus
//
// Purpose: Get the stauts of the connection.
//
// Arguments:
// pStatus [out] NETCON_STATUS
//
// Returns: S_OK or an error code
//
// Author: shaunco 17 Jul 1998
//
// Notes:
//
HRESULT CRasConnectionBase::HrGetStatus ( OUT NETCON_STATUS* pStatus) { Assert (pStatus);
// Initialize output parameters.
//
*pStatus = NCS_DISCONNECTED;
// Find the active RAS connection corresponding to this object if
// it exists.
//
HRASCONN hRasConn; HRESULT hr = HrFindRasConn (&hRasConn, NULL); if (S_OK == hr) { hr = HrRasGetNetconStatusFromRasConnectStatus ( hRasConn, pStatus);
// When the connection becomes disconnected between HrFindRas
// and HrRasGet calls above, ERROR_INVALID_HANLDE is returned
// this simply means that the connection has been disconnected.
//
if (HRESULT_FROM_WIN32(ERROR_INVALID_HANDLE) == hr) { Assert (NCS_DISCONNECTED == *pStatus); hr = S_OK; } } else if (S_FALSE == hr) { hr = S_OK;
if (!PszwDeviceName()) { *pStatus = NCS_HARDWARE_NOT_PRESENT; }
// NCS_HARDWARE_DISABLED ?
// NCS_HARDWARE_MALFUNCTION ?
} TraceError ("CRasConnectionBase::HrGetStatus", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Member: CRasConnectionBase::HrEnsureEntryPropertiesCached
//
// Purpose: Ensures that the member's corresponding to entry properties
// are cached by calling RasGetEntryProperties if needed.
//
// Arguments:
// (none)
//
// Returns: S_OK or an error code.
//
// Author: shaunco 17 Dec 1997
//
// Notes:
//
HRESULT CRasConnectionBase::HrEnsureEntryPropertiesCached () { HRESULT hr = S_OK;
// If we're not yet cached, or the cache is possibly out of date, we
// need to update ourselves. g_lRasEntryModifiedVersionEra is the global
// version indicator for RAS phonebook entry modifications. Our local
// version indicator is set in CacheProperties.
//
if (!m_fEntryPropertiesCached || (m_lRasEntryModifiedVersionEra != g_lRasEntryModifiedVersionEra)) { // We now need to enumerate all entries in this phonebook and
// find our details record with the matching guidId.
//
RASENUMENTRYDETAILS* aRasEntryDetails = NULL; DWORD cRasEntryDetails = 0;
// Impersonate the client.
//
HRESULT hrT = CoImpersonateClient (); TraceHr (ttidError, FAL, hrT, FALSE, "CoImpersonateClient");
// We need to continue if we're called in-proc (ie. if RPC_E_CALL_COMPLETE is returned).
if (SUCCEEDED(hrT) || (RPC_E_CALL_COMPLETE == hrT)) { hr = HrRasEnumAllEntriesWithDetails ( PszwPbkFile(), &aRasEntryDetails, &cRasEntryDetails);
if ((!aRasEntryDetails) || (!cRasEntryDetails)) { hr = HRESULT_FROM_WIN32 (ERROR_NOT_FOUND); } } else { hr = hrT; }
if (SUCCEEDED(hrT)) { hrT = CoRevertToSelf (); TraceHr (ttidError, FAL, hrT, FALSE, "CoRevertToSelf"); }
if (SUCCEEDED(hr)) { BOOL fNoGuidYet = (m_guidId == GUID_NULL);
RASENUMENTRYDETAILS* pDetails;
// Assume we don't find the entry.
//
hr = HRESULT_FROM_WIN32 (ERROR_NOT_FOUND);
for (DWORD i = 0; i < cRasEntryDetails; i++) { pDetails = &aRasEntryDetails[i];
if (pDetails->guidId == m_guidId) { CacheProperties (pDetails); hr = S_OK;
TraceTag (ttidWanCon, "HrRasEnumAllEntriesWithDetails found entry " "via guid (%S)", PszwEntryName()); break; } else if (fNoGuidYet && !lstrcmpW (PszwEntryName(), pDetails->szEntryName)) { CacheProperties (pDetails); hr = S_OK;
TraceTag (ttidWanCon, "HrRasEnumAllEntriesWithDetails found entry " "via entryname (%S)", PszwEntryName()); break; } }
MemFree (aRasEntryDetails); } else if (HRESULT_FROM_WIN32(ERROR_CANNOT_OPEN_PHONEBOOK) == hr) { hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); } } TraceError ("CRasConnectionBase::HrEnsureEntryPropertiesCached", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Member: CRasConnectionBase::HrFindRasConn
//
// Purpose: Searches for the active RAS connection that corresponds to
// this phone book and entry.
//
// Arguments:
// phRasConn [out] The returned handle to the RAS connection if it
// was found. NULL otherwise.
// pRasConn [out] Optional pointer to returned RASCONN structure
// if found.
//
// Returns: S_OK if found, S_FALSE if not, or an error code.
//
// Author: shaunco 29 Sep 1997
//
// Notes:
//
HRESULT CRasConnectionBase::HrFindRasConn ( OUT HRASCONN* phRasConn, OUT RASCONN* pRasConn OPTIONAL) { Assert (phRasConn); Assert (m_fInitialized);
HRESULT hr = S_OK;
// Initialize the output parameter.
//
*phRasConn = NULL;
// We need m_guidId to be valid. If it is GUID_NULL, it means
// we have an entry name with with to look it up.
//
if (GUID_NULL == m_guidId) { hr = HrEnsureEntryPropertiesCached (); }
if (SUCCEEDED(hr)) { hr = HrFindRasConnFromGuidId (&m_guidId, phRasConn, pRasConn);
}
TraceError ("CRasConnectionBase::HrFindRasConn", (S_FALSE == hr) ? S_OK : hr); return hr; }
//+---------------------------------------------------------------------------
//
// Member: CRasConnectionBase::HrLockAndRenameEntry
//
// Purpose: Renames the phone book entry and updates our entry name
// member atomically.
//
// Arguments:
// pszwNewName [in] The new name.
// pObj [in] Used to Lock the operation.
//
// Returns: S_OK or an error code.
//
// Author: shaunco 23 Sep 1997
//
// Notes:
//
HRESULT CRasConnectionBase::HrLockAndRenameEntry ( IN PCWSTR pszwNewName, IN CComObjectRootEx <CComMultiThreadModel>* pObj) { // Make sure the name is valid in the same phone book.
//
DWORD dwErr = RasValidateEntryName (PszwPbkFile (), pszwNewName);
HRESULT hr = HRESULT_FROM_WIN32 (dwErr); TraceHr (ttidError, FAL, hr, HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) == hr, "RasValidateEntryName", hr);
// We can ignore ERROR_ALREADY_EXISTS as it will happen when a user
// tries to change the case of the entry name.
//
if (SUCCEEDED(hr) || (HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) == hr)) { hr = HrEnsureEntryPropertiesCached (); if (SUCCEEDED(hr)) { // Lock the object and rename it.
//
CExceptionSafeComObjectLock EsLock (pObj);
dwErr = RasRenameEntry ( PszwPbkFile (), PszwEntryName (), pszwNewName);
hr = HRESULT_FROM_WIN32 (dwErr); TraceHr (ttidError, FAL, hr, FALSE, "RasRenameEntry");
if (SUCCEEDED(hr)) { SetEntryName (pszwNewName); } } }
TraceHr (ttidError, FAL, hr, FALSE, "CRasConnectionBase::HrLockAndRenameEntry"); return hr; }
//+---------------------------------------------------------------------------
//
// Member: CRasConnectionBase::HrGetRasConnectionInfo
//
// Purpose: Implementation of INetRasConnection::GetRasConnectionInfo
//
// Arguments:
// pRasConInfo [out] pointer to returned info
//
// Returns: S_OK or E_OUTOFMEMORY.
//
// Author: shaunco 20 Oct 1997
//
// Notes:
//
HRESULT CRasConnectionBase::HrGetRasConnectionInfo ( OUT RASCON_INFO* pRasConInfo) { Assert (m_fInitialized);
HRESULT hr;
// Validate parameters.
//
if (!pRasConInfo) { hr = E_POINTER; } else { hr = HrEnsureEntryPropertiesCached (); if (SUCCEEDED(hr)) { ZeroMemory (pRasConInfo, sizeof (*pRasConInfo));
hr = S_OK;
HRESULT hrT;
hrT = HrCoTaskMemAllocAndDupSz (PszwPbkFile(), &pRasConInfo->pszwPbkFile, MAX_PATH); if (FAILED(hrT)) { hr = hrT; }
hrT = HrCoTaskMemAllocAndDupSz (PszwEntryName(), &pRasConInfo->pszwEntryName, MAX_PATH); if (FAILED(hrT)) { hr = hrT; }
pRasConInfo->guidId = m_guidId;
if (FAILED(hr)) { RciFree (pRasConInfo);
AssertSz (!pRasConInfo->pszwPbkFile && !pRasConInfo->pszwEntryName, "RciFree should be zeroing the structure!"); } } } TraceError ("CRasConnectionBase::HrGetRasConnectionInfo", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Member: CRasConnectionBase::HrSetRasConnectionInfo
//
// Purpose: Implementation of INetRasConnection::SetRasConnectionInfo
//
// Arguments:
// pRasConInfo [in] info to set
//
// Returns: S_OK
//
// Author: shaunco 20 Oct 1997
//
// Notes:
//
HRESULT CRasConnectionBase::HrSetRasConnectionInfo ( IN const RASCON_INFO* pRasConInfo) { Assert (!m_fInitialized);
HRESULT hr = S_OK;
// Validate parameters.
//
if (!pRasConInfo) { hr = E_POINTER; } else if (!pRasConInfo->pszwPbkFile || (0 == lstrlenW (pRasConInfo->pszwPbkFile)) || !pRasConInfo->pszwEntryName || (0 == lstrlenW (pRasConInfo->pszwEntryName))) { hr = E_INVALIDARG; } else { SetPbkFile (pRasConInfo->pszwPbkFile); SetEntryName (pRasConInfo->pszwEntryName); m_guidId = pRasConInfo->guidId;
// We are now a full-fledged object.
//
m_fInitialized = TRUE; } TraceError ("CRasConnectionBase::HrSetRasConnectionInfo", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Member: CRasConnectionBase::HrGetRasConnectionHandle
//
// Purpose: Implementation of INetRasConnection::HrGetRasConnectionHandle
//
// Arguments:
// phRasConn [out] pointer to the returned RAS connection handle
//
// Returns: S_OK if connected, S_FALSE if not, error code otherwise.
//
// Author: CWill 09 Dec 1997
//
// Notes:
//
HRESULT CRasConnectionBase::HrGetRasConnectionHandle ( OUT HRASCONN* phRasConn) { HRESULT hr;
// Validate parameters.
//
if (!phRasConn) { hr = E_POINTER; } else if (!m_fInitialized) { hr = E_UNEXPECTED; } else { // Initialize the output parameter.
//
*phRasConn = 0;
hr = HrFindRasConn (phRasConn, NULL); }
TraceError ("CRasConnectionBase::HrGetRasConnectionHandle", (S_FALSE == hr) ? S_OK : hr); return hr; }
//+---------------------------------------------------------------------------
// IPersistNetConnection -
//
// For our persistent (across session) data, we choose to store only the
// the phonebook name and the guid Id of the RAS entry. We explicitly don't
// store the entry name because it can be changed externally. If it were
// we would have an orhpaned connection.
//
// When loading the connection from the persistent store, we need to
// enumerate all of the entries in the given phonebook looking for the one
// with the matching guid Id. Once found, the connection can successfully
// be loaded.
//
// Lead and trail characters for our persistent memory form.
//
static const WCHAR c_chwLead = 0x14; static const WCHAR c_chwTrail = 0x05;
//+---------------------------------------------------------------------------
//
// Member: CRasConnectionBase::HrPersistGetSizeMax
//
// Purpose: Implementation of IPersistNetConnection::GetSizeMax
//
// Arguments:
// pcbSize []
//
// Returns: S_OK or an error code
//
// Author: shaunco 4 Nov 1997
//
// Notes:
//
HRESULT CRasConnectionBase::HrPersistGetSizeMax ( OUT ULONG* pcbSize) { HRESULT hr = S_OK;
// Validate parameters.
//
if (!pcbSize) { hr = E_POINTER; } else if (!m_fInitialized) { hr = E_UNEXPECTED; } else { // Size the buffer for the following form:
// +--------------------------------------------+
// |0x14<phonebook file>\0<guid Id>\0<users>0x05|
// +--------------------------------------------+
//
*pcbSize = sizeof (c_chwLead) + CbOfSzAndTerm (PszwPbkFile()) + sizeof (m_guidId) + sizeof (m_fForAllUsers) + sizeof (c_chwTrail); } TraceError ("CRasConnectionBase::HrPersistGetSizeMax", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Member: CRasConnectionBase::HrPersistLoad
//
// Purpose: Implementation of IPersistNetConnection::Load
//
// Arguments:
// pbBuf []
// cbSize []
//
// Returns: S_OK or an error code
//
// Author: shaunco 4 Nov 1997
//
// Notes:
//
HRESULT CRasConnectionBase::HrPersistLoad ( IN const BYTE* pbBuf, IN ULONG cbSize) { TraceFileFunc(ttidWanCon); // The theoretical minimum size for the buffer is:
// (4 characters for a minimal path like 'c:\a')
//
const ULONG c_cbSizeMin = sizeof (c_chwLead) + (4 + 1) * sizeof(WCHAR) + sizeof (m_guidId) + sizeof (m_fForAllUsers) + sizeof (c_chwTrail);
HRESULT hr = E_INVALIDARG;
// Validate parameters.
//
if (!pbBuf) { hr = E_POINTER; } else if (cbSize < c_cbSizeMin) { hr = E_INVALIDARG; } // We can only accept one call on this method and only if we're not
// already initialized.
//
else if (m_fInitialized) { hr = E_UNEXPECTED; } else { // The buffer *should* look like this:
// +--------------------------------------------+
// |0x14<phonebook file>\0<guid Id>\0<users>0x05|
// +--------------------------------------------+
//
const WCHAR* pchw = reinterpret_cast<const WCHAR*>(pbBuf); const WCHAR* pchwMax; PCWSTR pszwPhonebook; GUID guidId; const GUID UNALIGNED *pguidId; BOOL fForAllUsers; const BOOL UNALIGNED *pfForAllUsers;
// The last valid pointer for the embedded strings.
//
pchwMax = reinterpret_cast<const WCHAR*>(pbBuf + cbSize - (sizeof (m_guidId) + sizeof (m_fForAllUsers) + sizeof (c_chwTrail)));
if (c_chwLead != *pchw) { goto finished; }
// Skip past our lead byte.
//
pchw++;
// Get m_strPbkFile. Search for the terminating null and make sure
// we find it before the end of the buffer. Using lstrlen to skip
// the string can result in an an AV in the event the string is
// not actually null-terminated.
//
for (pszwPhonebook = pchw; ; pchw++) { if (pchw >= pchwMax) { goto finished; } if (0 == *pchw) { pchw++; break; } }
// Get m_guidId
//
pguidId = reinterpret_cast<const GUID*>(pchw); CopyMemory(&guidId, pguidId, sizeof(guidId)); pguidId++;
// Get m_fForAllUsers
//
pfForAllUsers = reinterpret_cast<const BOOL*>(pguidId); CopyMemory(&fForAllUsers, pfForAllUsers, sizeof(fForAllUsers)); pfForAllUsers++;
// Check our trail byte.
//
pchw = reinterpret_cast<const WCHAR *>(pfForAllUsers); if (c_chwTrail != *pchw) { goto finished; }
TraceTag (ttidWanCon, "HrPersistLoad for %S", pszwPhonebook);
SetPbkFile (pszwPhonebook); m_fForAllUsers = fForAllUsers; m_guidId = guidId;
// We are now a full-fledged object.
//
m_fInitialized = TRUE; hr = S_OK;
finished: ; } TraceError ("CRasConnectionBase::HrPersistLoad", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Member: CRasConnectionBase::HrPersistSave
//
// Purpose: Implementation of IPersistNetConnection::Save
//
// Arguments:
// pbBuf []
// cbSize []
//
// Returns: S_OK or an error code
//
// Author: shaunco 4 Nov 1997
//
// Notes:
//
HRESULT CRasConnectionBase::HrPersistSave ( BYTE* pbBuf, ULONG cbSize) { HRESULT hr = S_OK;
// Validate parameters.
//
if (!pbBuf) { hr = E_POINTER; } else if (!m_fInitialized) { hr = E_UNEXPECTED; } else { // Make sure the user's buffer is big enough.
//
ULONG cbSizeRequired; SideAssert (SUCCEEDED(HrPersistGetSizeMax(&cbSizeRequired)));
if (cbSize < cbSizeRequired) { hr = E_INVALIDARG; } else { TraceTag (ttidWanCon, "HrPersistSave for %S (%S)", PszwEntryName (), PszwPbkFile ());
hr = HrEnsureEntryPropertiesCached (); if (SUCCEEDED(hr)) { // Make the buffer look like this when we're done:
// +--------------------------------------------+
// |0x14<phonebook file>\0<guid Id>\0<users>0x05|
// +--------------------------------------------+
//
WCHAR* pchw = reinterpret_cast<WCHAR*>(pbBuf);
// Put our lead byte.
//
*pchw = c_chwLead; pchw++;
// Put m_strPbkFile
//
ULONG cchw = lstrlenW (PszwPbkFile()); lstrcpyW (pchw, PszwPbkFile()); pchw += cchw + 1;
// Put m_guidId
//
GUID UNALIGNED *pguidId = reinterpret_cast<GUID*>(pchw); CopyMemory(pguidId, &GuidId(), sizeof(*pguidId)); pguidId++;
// Put m_fForAllUsers
//
BOOL UNALIGNED * pfForAllUsers = reinterpret_cast<BOOL*>(pguidId); CopyMemory(pfForAllUsers, &m_fForAllUsers, sizeof(*pfForAllUsers)); pfForAllUsers++;
// Put our trail byte.
//
pchw = reinterpret_cast<WCHAR*>(pfForAllUsers); *pchw = c_chwTrail; pchw++;
AssertSz (pbBuf + cbSizeRequired == (BYTE*)pchw, "pch isn't pointing where it should be."); } } } TraceError ("CRasConnectionBase::HrPersistSave", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Member: CRasConnectionBase::HrEnsureHNetPropertiesCached
//
// Purpose: Makes sure home networking properties are up-to-date
//
// Arguments:
// (none)
//
// Returns: S_OK if m_pHNetProperties is now valid (success)
// S_FALSE if it's not currently possible to update the properties
// (e.g., recursive attempt to update)
//
// Author: jonburs 16 August 2000
//
// Notes:
//
HRESULT CRasConnectionBase::HrEnsureHNetPropertiesCached () { HRESULT hr = S_OK;
if (!m_fHNetPropertiesCached || m_lHNetModifiedEra != g_lHNetModifiedEra) { //
// Our cached properties are possibly out of date. Check
// to see that this is not a recursive entry
//
if (0 == InterlockedExchange(&m_lUpdatingHNetProperties, 1)) { IHNetConnection *pHNetConn; HNET_CONN_PROPERTIES *pProps;
hr = HrGetIHNetConnection(&pHNetConn);
if (SUCCEEDED(hr)) { hr = pHNetConn->GetProperties(&pProps); ReleaseObj(pHNetConn);
if (SUCCEEDED(hr)) { //
// Copy retrieved properties to member structure.
//
CopyMemory( reinterpret_cast<PVOID>(&m_HNetProperties), reinterpret_cast<PVOID>(pProps), sizeof(m_HNetProperties) );
CoTaskMemFree(pProps);
//
// Update our era, and note that we have valid properties
//
InterlockedExchange(&m_lHNetModifiedEra, g_lHNetModifiedEra); m_fHNetPropertiesCached = TRUE;
hr = S_OK; } } else { //
// If we don't yet have a record of this connection w/in the
// home networking store, HrGetIHNetConnection will fail (as
// we ask it not to create new entries). We therefore convert
// failure to S_FALSE, which means we can't retrieve this info
// right now.
//
hr = S_FALSE; }
//
// We're no longer updating our properties
//
InterlockedExchange(&m_lUpdatingHNetProperties, 0); } else { //
// Update is alredy going on (possibly an earlier call on
// the same thread). Return S_FALSE.
//
hr = S_FALSE; } }
return hr; }
//+---------------------------------------------------------------------------
//
// Member: HrGetIHNetConnection
//
// Purpose: Retrieves the IHNetConnection for this connection
//
// Arguments:
//
// Returns: S_OK on success; error otherwise
//
// Author: jonburs 16 August 2000
//
// Notes:
//
HRESULT CRasConnectionBase::HrGetIHNetConnection ( OUT IHNetConnection **ppHNetConnection) { HRESULT hr; IHNetCfgMgr *pCfgMgr; GUID guid;
Assert(ppHNetConnection);
hr = HrGetHNetCfgMgr(&pCfgMgr);
if (SUCCEEDED(hr)) { guid = GuidId();
hr = pCfgMgr->GetIHNetConnectionForGuid( &guid, FALSE, FALSE, ppHNetConnection );
ReleaseObj(pCfgMgr); }
return hr; }
//+---------------------------------------------------------------------------
//
// Member: HrGetIHNetConnection
//
// Purpose: Retrieves the IHNetConnection for this connection
//
// Arguments:
//
// Returns: S_OK on success; error otherwise
//
// Author: jonburs 16 August 2000
//
// Notes:
//
HRESULT CRasConnectionBase::HrIsConnectionFirewalled( OUT BOOL* pfFirewalled) { *pfFirewalled = FALSE;
HRESULT hr = S_OK; BOOL fHasPermission = FALSE; hr = HrEnsureHNetPropertiesCached(); if (S_OK == hr) { *pfFirewalled = m_HNetProperties.fFirewalled;
if (*pfFirewalled) { // A Connection is only firewalled if the firewall is currently running, so
// we return FALSE if the permission denies the firewall from running.
hr = HrEnsureValidNlaPolicyEngine(); TraceHr(ttidError, FAL, hr, (S_FALSE == hr), "CRasConnectionBase::HrIsConnectionFirewalled calling HrEnsureValidNlaPolicyEngine", hr);
if (SUCCEEDED(hr)) { hr = m_pNetMachinePolicies->VerifyPermission(NCPERM_PersonalFirewallConfig, &fHasPermission); if (SUCCEEDED(hr) && !fHasPermission) { *pfFirewalled = FALSE; } } } } return hr; }
HRESULT CRasConnectionBase::HrEnsureValidNlaPolicyEngine() { HRESULT hr = S_FALSE; // Assume we already have the object
if (!m_pNetMachinePolicies) { hr = CoCreateInstance(CLSID_NetGroupPolicies, NULL, CLSCTX_INPROC, IID_INetMachinePolicies, reinterpret_cast<void**>(&m_pNetMachinePolicies)); } return hr; }
|