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

553 lines
13 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1997.
//
// File: N C N E T C O N . C P P
//
// Contents: Common routines for dealing with the connections interfaces.
//
// Notes: Pollute this under penalty of death.
//
// Author: shaunco 20 Aug 1998
//
//----------------------------------------------------------------------------
#include <pch.h>
#pragma hdrstop
#include <atlbase.h>
#include "nccom.h"
#include "ncnetcon.h"
#include "netconp.h"
#include "ncras.h"
#include "ncreg.h"
#include "ncconv.h"
//+---------------------------------------------------------------------------
//
// Function: FreeNetconProperties
//
// Purpose: Free the memory associated with the output parameter of
// INetConnection->GetProperties. This is a helper function
// used by clients of INetConnection.
//
// Arguments:
// pProps [in] The properties to free.
//
// Returns: nothing.
//
// Author: shaunco 1 Feb 1998
//
// Notes:
//
VOID
FreeNetconProperties (
IN NETCON_PROPERTIES* pProps)
{
if (pProps)
{
CoTaskMemFree (pProps->pszwName);
CoTaskMemFree (pProps->pszwDeviceName);
CoTaskMemFree (pProps);
}
}
//+---------------------------------------------------------------------------
//
// Function: HrGetConnectionPersistData
//
// Purpose: Get the persistent form of a connection. This can be used
// to later get back to the INetConnection interface with a call
// to HrGetConnectionFromPersistData.
//
// Arguments:
// pConn [in] Connection to get persist data from.
// ppbData [out] Address of where to return pointer to data.
// pcbSize [out] Address of where to return the size of the data.
// pclsid [out] Address of where to return the CLSID of the connection.
//
// Returns: S_OK or an error code
//
// Author: shaunco 20 Aug 1998
//
// Notes: Free *ppbData with MemFree.
//
HRESULT
HrGetConnectionPersistData (
IN INetConnection* pConn,
OUT BYTE** ppbData,
OUT ULONG* pcbSize,
OUT CLSID* pclsid OPTIONAL)
{
Assert (pConn);
Assert (ppbData);
Assert (pcbSize);
// pclsid is optional.
// Initialize the output parameters.
//
*ppbData = NULL;
*pcbSize = 0;
if (pclsid)
{
*pclsid = GUID_NULL;
}
// Get the IPersistNetConnection interfaces.
//
IPersistNetConnection* pPersist;
HRESULT hr = HrQIAndSetProxyBlanket(pConn, &pPersist);
if (SUCCEEDED(hr))
{
// Return the CLSID if requested.
//
if (pclsid)
{
hr = pPersist->GetClassID (pclsid);
TraceHr(ttidError, FAL, hr, FALSE, "pPersist->GetClassID");
}
if (SUCCEEDED(hr))
{
// Get the size required, allocated a buffer, and get the data.
//
BYTE* pbData;
ULONG cbData;
hr = pPersist->GetSizeMax (&cbData);
TraceHr(ttidError, FAL, hr, FALSE, "pPersist->GetSizeMax");
if (SUCCEEDED(hr))
{
hr = E_OUTOFMEMORY;
pbData = (BYTE*)MemAlloc (cbData);
if (pbData)
{
hr = pPersist->Save (pbData, cbData);
TraceHr(ttidError, FAL, hr, FALSE, "pPersist->Save");
if (SUCCEEDED(hr))
{
*ppbData = pbData;
*pcbSize = cbData;
}
else
{
MemFree (pbData);
}
}
}
}
ReleaseObj (pPersist);
}
TraceError("HrGetConnectionPersistData", hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrGetConnectionFromPersistData
//
// Purpose: Get an INetConnection interface given the persistent form of
// the connection.
//
// Arguments:
// clsid [in] CLSID to CoCreateInstance with.
// pbData [in] Pointer to connection's persist data.
// cbData [in] Size of the data in bytes.
// ppConn [out] Address of where to return the pointer to the
// INetConnection interface.
//
// Returns: S_OK or an error code.
//
// Author: shaunco 2 Nov 1998
//
// Notes:
//
HRESULT
HrGetConnectionFromPersistData (
IN const CLSID& clsid,
IN const BYTE* pbData,
IN ULONG cbData,
IN REFIID riid,
OUT VOID** ppv)
{
Assert (pbData);
Assert (cbData);
Assert (ppv);
HRESULT hr;
// Initialize the output parameter.
//
*ppv = NULL;
// Create a connection object and get an IPersistNetConnection
// interface pointer on it.
//
IPersistNetConnection* pPersist;
hr = HrCreateInstance(
clsid,
CLSCTX_LOCAL_SERVER | CLSCTX_NO_CODE_DOWNLOAD,
&pPersist);
TraceHr(ttidError, FAL, hr, FALSE, "HrCreateInstance");
if (SUCCEEDED(hr))
{
// Initialize the connection object using the persist data.
//
hr = pPersist->Load (pbData, cbData);
TraceHr(ttidError, FAL, hr, FALSE,
"pPersist->Load: pbData=0x%p, cbData=%u",
pbData, cbData);
if (SUCCEEDED(hr))
{
// Return an INetConnection interface pointer.
//
hr = pPersist->QueryInterface(riid, ppv);
TraceHr(ttidError, FAL, hr, FALSE, "pPersist->QueryInterface");
if (SUCCEEDED(hr))
{
NcSetProxyBlanket (reinterpret_cast<IUnknown *>(*ppv));
}
}
ReleaseObj (pPersist);
}
TraceError("HrGetConnectionFromPersistData", hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: FIsValidConnectionName
//
// Purpose: Determines if the given connection name is valid.
//
// Arguments:
// pszName [in] Connection name to test
//
// Returns: TRUE if name is valid, FALSE if not
//
// Author: danielwe 14 Sep 1998
//
// Notes:
//
BOOL
FIsValidConnectionName (
IN PCWSTR pszName)
{
static const WCHAR c_szInvalidChars[] = L"\\/:*?\"<>|\t";
const WCHAR* pchName;
if (lstrlen(pszName) > RASAPIP_MAX_ENTRY_NAME)
{
return FALSE;
}
DWORD dwNonSpaceChars = 0;
for (pchName = pszName; pchName && *pchName; pchName++)
{
if (wcschr(c_szInvalidChars, *pchName))
{
return FALSE;
}
if (*pchName != L' ')
{
dwNonSpaceChars++;
}
}
if (!dwNonSpaceChars)
{
return FALSE;
}
return TRUE;
}
#define REGKEY_NETWORK_CONNECTIONS \
L"System\\CurrentControlSet\\Control\\Network\\Connections"
#define REGVAL_ATLEASTONELANSHOWICON \
L"AtLeastOneLanShowIcon"
VOID
SetOrQueryAtLeastOneLanWithShowIcon (
IN BOOL fSet,
IN BOOL fSetValue,
OUT BOOL* pfQueriedValue)
{
HRESULT hr;
HKEY hkey;
REGSAM samDesired;
DWORD dwValue;
samDesired = (fSet) ? KEY_WRITE : KEY_READ;
hr = HrRegOpenKeyEx (
HKEY_LOCAL_MACHINE,
REGKEY_NETWORK_CONNECTIONS,
samDesired,
&hkey);
if (S_OK == hr)
{
if (fSet)
{
dwValue = (fSetValue) ? 1: 0;
hr = HrRegSetDword (
hkey,
REGVAL_ATLEASTONELANSHOWICON,
dwValue);
}
else
{
Assert (pfQueriedValue);
hr = HrRegQueryDword (
hkey,
REGVAL_ATLEASTONELANSHOWICON,
&dwValue);
*pfQueriedValue = !!dwValue;
}
RegCloseKey (hkey);
}
}
BOOL
FAnyReasonToEnumerateConnectionsForShowIconInfo (
VOID)
{
// If any active RAS connections exist, might as well return TRUE
// because they will probably have the "showicon" bit turned on.
//
if (FExistActiveRasConnections ())
{
return TRUE;
}
BOOL fRet = FALSE;
// If the LAN connection manager has previously noted that at least
// one LAN connection has the showicon bit set, return TRUE.
//
SetOrQueryAtLeastOneLanWithShowIcon (
FALSE, // query the value
FALSE,
&fRet);
return fRet;
}
//+---------------------------------------------------------------------------
//
// Function: HrSafeArrayFromNetConPropertiesEx
//
// Purpose: Create a safe array that can be marshaled across processes.
//
//
//
// Arguments:
// pPropsEx [in] Properties to use to build the safe array.
// ppsaProperties [out] Safe array in which to store data.
//
// Returns: HRESULT
//
// Author: ckotze 19 Mar 2001
//
// Notes: Caller must free array and contents.
//
//
HRESULT
HrSafeArrayFromNetConPropertiesEx (
IN NETCON_PROPERTIES_EX* pPropsEx,
OUT SAFEARRAY** ppsaProperties)
{
HRESULT hr = S_OK;
SAFEARRAYBOUND rgsaBound[1] = {0};
if (!pPropsEx)
{
return E_INVALIDARG;
}
if (!ppsaProperties)
{
return E_POINTER;
}
rgsaBound[0].cElements = NCP_ELEMENTS;
rgsaBound[0].lLbound = 0;
*ppsaProperties = SafeArrayCreate(VT_VARIANT, 1, rgsaBound);
if (*ppsaProperties)
{
CPropertiesEx peProps(pPropsEx);
for (LONG i = NCP_DWSIZE; i <= NCP_MAX; i++)
{
CComVariant varField;
hr = peProps.GetField(i, varField);
if (SUCCEEDED(hr))
{
hr = SafeArrayPutElement(*ppsaProperties, &i, reinterpret_cast<void*>(&varField));
}
if (FAILED(hr))
{
break;
}
}
}
else
{
hr = E_OUTOFMEMORY;
}
TraceHr (ttidError, FAL, hr, FALSE, "HrSafeArrayFromNetConPropertiesEx");
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrNetConPropertiesExFromSafeArray
//
// Purpose: Rebuilds a NETCON_PROPERTIES_EX* structure from the safearray.
//
//
//
// Arguments:
// psaProperties [in] The safe array containing the data
// ppPropsEx [out] Structure containing the properties
//
// Returns: HRESULT - S_OK if valid, else an error.
//
// Author: ckotze 19 Mar 2001
//
// Notes: Caller must free ppPropsEx using HrFreeNetConProperties2
//
HRESULT HrNetConPropertiesExFromSafeArray(
IN SAFEARRAY* psaProperties,
OUT NETCON_PROPERTIES_EX** ppPropsEx)
{
HRESULT hr = S_OK;
LONG lLBound;
LONG lUBound;
if (!psaProperties)
{
return E_INVALIDARG;
}
*ppPropsEx = reinterpret_cast<NETCON_PROPERTIES_EX*>(CoTaskMemAlloc(sizeof(NETCON_PROPERTIES_EX)));
if (*ppPropsEx)
{
hr = SafeArrayGetLBound(psaProperties, 1, &lLBound);
if (SUCCEEDED(hr))
{
hr = SafeArrayGetUBound(psaProperties, 1, &lUBound);
if (SUCCEEDED(hr))
{
CPropertiesEx PropEx(*ppPropsEx);
for (LONG i = lLBound; i <= lUBound; i++)
{
CComVariant varField;
hr = SafeArrayGetElement(psaProperties, &i, reinterpret_cast<LPVOID>(&varField));
if (SUCCEEDED(hr))
{
hr = PropEx.SetField(i, varField);
}
if (FAILED(hr))
{
break;
}
}
}
}
}
else
{
hr = E_OUTOFMEMORY;
}
TraceHr (ttidError, FAL, hr, FALSE, "HrNetConPropertiesExFromSafeArray");
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrFreeNetConProperties2
//
// Purpose: Free all strings in the structure and then free the structure.
//
//
//
// Arguments:
// pPropsEx [in] The properties to free.
//
// Returns: HRESULT - S_OK if success else an error
//
// Author: ckotze 19 Mar 2001
//
// Notes:
//
HRESULT HrFreeNetConProperties2(NETCON_PROPERTIES_EX* pPropsEx)
{
HRESULT hr = S_OK;
Assert(pPropsEx);
if (pPropsEx)
{
if (pPropsEx->bstrName)
{
SysFreeString(pPropsEx->bstrName);
}
if (pPropsEx->bstrDeviceName)
{
SysFreeString(pPropsEx->bstrDeviceName);
}
if (pPropsEx->bstrPhoneOrHostAddress)
{
SysFreeString(pPropsEx->bstrPhoneOrHostAddress);
}
if (pPropsEx->bstrPersistData)
{
SysFreeString(pPropsEx->bstrPersistData);
}
CoTaskMemFree(pPropsEx);
}
else
{
hr = E_INVALIDARG;
}
return hr;
}