Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1892 lines
62 KiB

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1997.
//
// File: N C N E T C F G . C P P
//
// Contents: Common routines for dealing with INetCfg interfaces.
//
// Notes:
//
// Author: shaunco 24 Mar 1997
//
//----------------------------------------------------------------------------
#include <pch.h>
#pragma hdrstop
#include "netcfgx.h"
#include "netcfgn.h"
#include "netcfgp.h"
#include "ncdebug.h"
#include "ncbase.h"
#include "ncmisc.h"
#include "ncnetcfg.h"
#include "ncreg.h"
#include "ncvalid.h"
extern const WCHAR c_szRegKeyAnswerFileMap[];
extern const WCHAR c_szInfId_MS_AppleTalk[];
extern const WCHAR c_szInfId_MS_AtmArps[];
extern const WCHAR c_szInfId_MS_AtmElan[];
extern const WCHAR c_szInfId_MS_AtmLane[];
extern const WCHAR c_szInfId_MS_AtmUni[];
extern const WCHAR c_szInfId_MS_DHCPServer[];
extern const WCHAR c_szInfId_MS_GPC[];
extern const WCHAR c_szInfId_MS_IrDA[];
extern const WCHAR c_szInfId_MS_IrdaMiniport[];
extern const WCHAR c_szInfId_MS_IrModemMiniport[];
extern const WCHAR c_szInfId_MS_Isotpsys[];
extern const WCHAR c_szInfId_MS_L2TP[];
extern const WCHAR c_szInfId_MS_L2tpMiniport[];
extern const WCHAR c_szInfId_MS_MSClient[];
extern const WCHAR c_szInfId_MS_NdisWan[];
extern const WCHAR c_szInfId_MS_NdisWanAtalk[];
extern const WCHAR c_szInfId_MS_NdisWanBh[];
extern const WCHAR c_szInfId_MS_NdisWanIp[];
extern const WCHAR c_szInfId_MS_NdisWanIpx[];
extern const WCHAR c_szInfId_MS_NdisWanNbfIn[];
extern const WCHAR c_szInfId_MS_NdisWanNbfOut[];
extern const WCHAR c_szInfId_MS_NetBIOS[];
extern const WCHAR c_szInfId_MS_NetBT[];
extern const WCHAR c_szInfId_MS_NetBT_SMB[];
extern const WCHAR c_szInfId_MS_NetMon[];
extern const WCHAR c_szInfId_MS_NWClient[];
extern const WCHAR c_szInfId_MS_NWIPX[];
extern const WCHAR c_szInfId_MS_NWNB[];
extern const WCHAR c_szInfId_MS_NwSapAgent[];
extern const WCHAR c_szInfId_MS_NWSPX[];
extern const WCHAR c_szInfId_MS_PPPOE[];
extern const WCHAR c_szInfId_MS_PppoeMiniport[];
extern const WCHAR c_szInfId_MS_PPTP[];
extern const WCHAR c_szInfId_MS_PptpMiniport[];
extern const WCHAR c_szInfId_MS_PSched[];
extern const WCHAR c_szInfId_MS_PSchedMP[];
extern const WCHAR c_szInfId_MS_PSchedPC[];
extern const WCHAR c_szInfId_MS_PtiMiniport[];
extern const WCHAR c_szInfId_MS_RasCli[];
extern const WCHAR c_szInfId_MS_RasMan[];
extern const WCHAR c_szInfId_MS_RasSrv[];
extern const WCHAR c_szInfId_MS_RawWan[];
extern const WCHAR c_szInfId_MS_Server[];
extern const WCHAR c_szInfId_MS_Steelhead[];
extern const WCHAR c_szInfId_MS_Streams[];
extern const WCHAR c_szInfId_MS_TCPIP[];
#pragma BEGIN_CONST_SECTION
// Warning: This must stay sorted on component id!
// Hint: With VSlick, use 'sort_on_selection AI' to resort this.
//
extern const __declspec(selectany) COMPONENT_INFO c_mapComponents [] =
{
{ c_szInfId_MS_AppleTalk, &GUID_DEVCLASS_NETTRANS, L"netatlk.inf" },
{ c_szInfId_MS_AtmArps, &GUID_DEVCLASS_NETTRANS, L"netaarps.inf"},
{ c_szInfId_MS_AtmElan, &GUID_DEVCLASS_NET, L"netlanem.inf"},
{ c_szInfId_MS_AtmLane, &GUID_DEVCLASS_NETTRANS, L"netlanep.inf"},
{ c_szInfId_MS_AtmUni, &GUID_DEVCLASS_NETTRANS, L"netauni.inf"},
{ c_szInfId_MS_DHCPServer, &GUID_DEVCLASS_NETSERVICE, L"netdhcps.inf" },
{ c_szInfId_MS_IrDA, &GUID_DEVCLASS_NETTRANS, L"netirda.inf" },
{ c_szInfId_MS_IrdaMiniport, &GUID_DEVCLASS_NET, L"netrasa.inf" },
{ c_szInfId_MS_IrModemMiniport, &GUID_DEVCLASS_NET, L"netrasa.inf" },
{ c_szInfId_MS_Isotpsys, &GUID_DEVCLASS_NETTRANS, L"nettp4.inf" },
{ c_szInfId_MS_L2TP, &GUID_DEVCLASS_NETTRANS, L"netrast.inf" },
{ c_szInfId_MS_L2tpMiniport, &GUID_DEVCLASS_NET, L"netrasa.inf" },
{ c_szInfId_MS_MSClient, &GUID_DEVCLASS_NETCLIENT, L"netmscli.inf" },
{ c_szInfId_MS_NdisWan, &GUID_DEVCLASS_NETTRANS, L"netrast.inf" },
{ c_szInfId_MS_NdisWanAtalk, &GUID_DEVCLASS_NET, L"netrasa.inf" },
{ c_szInfId_MS_NdisWanBh, &GUID_DEVCLASS_NET, L"netrasa.inf" },
{ c_szInfId_MS_NdisWanIp, &GUID_DEVCLASS_NET, L"netrasa.inf" },
{ c_szInfId_MS_NdisWanIpx, &GUID_DEVCLASS_NET, L"netrasa.inf" },
{ c_szInfId_MS_NdisWanNbfIn, &GUID_DEVCLASS_NET, L"netrasa.inf" },
{ c_szInfId_MS_NdisWanNbfOut, &GUID_DEVCLASS_NET, L"netrasa.inf" },
{ c_szInfId_MS_NetBIOS, &GUID_DEVCLASS_NETSERVICE, L"netnb.inf" },
{ c_szInfId_MS_NetBT, &GUID_DEVCLASS_NETTRANS, L"nettcpip.inf" },
{ c_szInfId_MS_NetBT_SMB, &GUID_DEVCLASS_NETTRANS, L"nettcpip.inf" },
{ c_szInfId_MS_NetMon, &GUID_DEVCLASS_NETTRANS, L"netnm.inf" },
{ c_szInfId_MS_NWClient, &GUID_DEVCLASS_NETCLIENT, L"netnwcli.inf" },
{ c_szInfId_MS_NWIPX, &GUID_DEVCLASS_NETTRANS, L"netnwlnk.inf" },
{ c_szInfId_MS_NWNB, &GUID_DEVCLASS_NETTRANS, L"netnwlnk.inf" },
{ c_szInfId_MS_NwSapAgent, &GUID_DEVCLASS_NETSERVICE, L"netsap.inf" },
{ c_szInfId_MS_NWSPX, &GUID_DEVCLASS_NETTRANS, L"netnwlnk.inf" },
{ c_szInfId_MS_PPPOE, &GUID_DEVCLASS_NETTRANS, L"netrast.inf" },
{ c_szInfId_MS_PppoeMiniport, &GUID_DEVCLASS_NET, L"netrasa.inf" },
{ c_szInfId_MS_PPTP, &GUID_DEVCLASS_NETTRANS, L"netrast.inf" },
{ c_szInfId_MS_PptpMiniport, &GUID_DEVCLASS_NET, L"netrasa.inf" },
{ c_szInfId_MS_PSched, &GUID_DEVCLASS_NETSERVICE, L"netpschd.inf" },
{ c_szInfId_MS_PSchedMP, &GUID_DEVCLASS_NET, L"netpsa.inf" },
{ c_szInfId_MS_PSchedPC, &GUID_DEVCLASS_NETSERVICE, L"netpschd.inf" },
{ c_szInfId_MS_PtiMiniport, &GUID_DEVCLASS_NET, L"netrasa.inf" },
{ c_szInfId_MS_RasCli, &GUID_DEVCLASS_NETSERVICE, L"netrass.inf" },
{ c_szInfId_MS_RasMan, &GUID_DEVCLASS_NETSERVICE, L"netrass.inf" },
{ c_szInfId_MS_RasSrv, &GUID_DEVCLASS_NETSERVICE, L"netrass.inf" },
{ c_szInfId_MS_RawWan, &GUID_DEVCLASS_NETTRANS, L"netrwan.inf" },
{ c_szInfId_MS_Server, &GUID_DEVCLASS_NETSERVICE, L"netserv.inf" },
{ c_szInfId_MS_Steelhead, &GUID_DEVCLASS_NETSERVICE, L"netrass.inf" },
{ c_szInfId_MS_Streams, &GUID_DEVCLASS_NETTRANS, L"netstrm.inf" },
{ c_szInfId_MS_TCPIP, &GUID_DEVCLASS_NETTRANS, L"nettcpip.inf" },
{ L"ms_wanarp", &GUID_DEVCLASS_NET, L"netrast.inf" },
};
#pragma END_CONST_SECTION
//+---------------------------------------------------------------------------
//
// Function: NCompareComponentIds
//
// Purpose: Compare function for bsearch.
//
// Arguments:
// ppszComp1 [in] pointer to pointer to a component id
// ppszComp2 [in] pointer to pointer to a component id
//
// Returns: < 0 if pvComp1 is less than pvComp2
// 0 if they are equal
// > 0 if pvComp1 is greater than pvComp2
//
// Author: shaunco 27 Jul 1997
//
// Notes:
//
int __cdecl
NCompareComponentIds (
IN const PCWSTR* ppszComp1,
IN const PCWSTR* ppszComp2)
{
return lstrcmpiW (*ppszComp1, *ppszComp2);
}
//+---------------------------------------------------------------------------
//
// Function: PComponentInfoFromComponentId
//
// Purpose: Return the COMPONENT_INFO record within c_mapComponents
// having the specified component id.
//
// Arguments:
// pszComponentId [in] The requested component id.
//
// Returns: NULL if not found.
//
// Author: shaunco 27 Jul 1997
//
// Notes:
//
inline
const COMPONENT_INFO*
PComponentInfoFromComponentId (
PCWSTR pszComponentId)
{
// For debug builds, check that c_mapComponents is sorted properley.
// If it isn't, bsearch (called below) won't work. Only perform this
// check once because the map doesn't change.
//
#ifdef DBG
static BOOL fCheckedSorted = FALSE;
if (!fCheckedSorted)
{
fCheckedSorted = TRUE;
for (UINT i = 1; i < celems (c_mapComponents); i++)
{
PCWSTR pszComp1 = c_mapComponents [i-1].pszComponentId;
PCWSTR pszComp2 = c_mapComponents [i] .pszComponentId;
if (NCompareComponentIds (&pszComp1, &pszComp2) >= 0)
{
AssertFmt (FALSE, FAL,
"'%S' in c_mapComponents is out of order! "
"Component installation may fail in bizarre ways!",
pszComp2);
}
}
}
#endif
typedef int (__cdecl *PFNCOMPARE)(const void *, const void *);
PFNCOMPARE pfn = reinterpret_cast<PFNCOMPARE>(NCompareComponentIds);
return static_cast<const COMPONENT_INFO*>
(bsearch (&pszComponentId,
&c_mapComponents->pszComponentId,
celems (c_mapComponents),
sizeof (c_mapComponents[0]),
pfn));
}
//+---------------------------------------------------------------------------
//
// Function: FClassGuidFromComponentId
//
// Purpose: Given a component id, returns the class guid associated with
// it.
//
// Arguments:
// pszComponentId [in] Component id to look up.
// pguidClass [out] Class guid to be returned.
//
// Returns: TRUE if component was found, FALSE if not.
//
// Author: danielwe 17 Jun 1997
//
// Notes:
//
BOOL
FClassGuidFromComponentId (
PCWSTR pszComponentId,
const GUID** ppguidClass)
{
Assert(ppguidClass);
// Initialize output parameter.
//
*ppguidClass = NULL;
const COMPONENT_INFO* pComponentInfo =
PComponentInfoFromComponentId (pszComponentId);
if (pComponentInfo)
{
*ppguidClass = pComponentInfo->pguidClass;
return TRUE;
}
TraceTag (ttidNetcfgBase,
"Found no match for %S in FClassGuidFromComponentId.",
pszComponentId);
return FALSE;
}
//+---------------------------------------------------------------------------
//
// Function: FInfFileFromComponentId
//
// Purpose: Given a component ID, returns the INF file name it lives in.
//
// Arguments:
// pszComponentId [in] Component id to look up.
// pszInfFile [out] INF file name to be returned.
// (must be _MAX_PATH long).
//
// Returns: TRUE if component was found, FALSE if not.
//
// Author: shaunco 27 Jul 1997
//
// Notes:
//
BOOL
FInfFileFromComponentId (
PCWSTR pszComponentId,
PWSTR pszInfFile)
{
Assert(pszComponentId);
Assert(pszInfFile);
// Initialize output parameter.
//
*pszInfFile = 0;
const COMPONENT_INFO* pComponentInfo =
PComponentInfoFromComponentId (pszComponentId);
if (pComponentInfo)
{
wcsncpy (pszInfFile, pComponentInfo->pszInfFile, _MAX_PATH);
pszInfFile [_MAX_PATH - 1] = 0;
return TRUE;
}
TraceTag (ttidNetcfgBase,
"Found no match for %S in FInfFileFromComponentId.",
pszComponentId);
return FALSE;
}
//+---------------------------------------------------------------------------
//
// Function: FGetInstanceGuidOfComponentFromAnswerFileMap
//
// Purpose: Maps a component instance in the answer file to
// its instance guid.
//
// Arguments:
// pszComponentId [in] Name of component to get guid of.
// pguid [out] Returns instance GUID of that component.
//
// Returns: TRUE if successful, FALSE if the component was not located.
//
BOOL
FGetInstanceGuidOfComponentFromAnswerFileMap (
IN PCWSTR pszComponentId,
OUT GUID* pguid)
{
HRESULT hr;
BOOL fFound = FALSE;
// Component not found as already installed. Need to examine the
// AnswerFileMap in the registry.
//
HKEY hkey;
hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegKeyAnswerFileMap,
KEY_QUERY_VALUE, &hkey);
if (S_OK == hr)
{
WCHAR szGuid [c_cchGuidWithTerm];
DWORD cbData = sizeof (szGuid);
hr = HrRegQuerySzBuffer(hkey, pszComponentId, szGuid, &cbData);
if (S_OK == hr)
{
hr = IIDFromString(szGuid, pguid);
fFound = (S_OK == hr);
}
RegCloseKey(hkey);
}
#ifdef ENABLETRACE
if (FAILED(hr))
{
TraceTag(ttidNetcfgBase, "FGetInstanceGuidOfComponentInAnswerFile: "
"could not locate instance GUID of %S", pszComponentId);
}
#endif
return fFound;
}
//+---------------------------------------------------------------------------
//
// Function: FGetInstanceGuidOfComponentInAnswerFile
//
// Purpose: Maps a component instance in the answer file to
// its instance guid.
//
// Arguments:
// pszComponentId [in] Name of component to get guid of.
// pnc [in] INetCfg interface
// pguid [out] Returns instance GUID of that component.
//
// Returns: TRUE if successful, FALSE if the component was not located.
//
BOOL
FGetInstanceGuidOfComponentInAnswerFile(
IN PCWSTR pszComponentId,
IN INetCfg* pnc,
OUT LPGUID pguid)
{
static char __FUNCNAME__[] = "FGetInstanceGuidOfComponentInAnswerFile";
Assert (pszComponentId);
AssertValidReadPtr(pnc);
AssertValidWritePtr(pguid);
// Search for the component.
//
INetCfgComponent* pncc;
HRESULT hr = pnc->FindComponent (pszComponentId, &pncc);
if (S_OK == hr)
{
hr = pncc->GetInstanceGuid (pguid);
ReleaseObj(pncc);
}
else
{
// Component not found as already installed. Need to examine the
// AnswerFileMap in the registry.
//
HKEY hkey;
hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegKeyAnswerFileMap,
KEY_QUERY_VALUE, &hkey);
if (S_OK == hr)
{
WCHAR szGuid [c_cchGuidWithTerm];
DWORD cbData = sizeof (szGuid);
hr = HrRegQuerySzBuffer(hkey, pszComponentId, szGuid, &cbData);
if (S_OK == hr)
{
hr = IIDFromString(szGuid, pguid);
}
RegCloseKey(hkey);
}
#ifdef ENABLETRACE
if (FAILED(hr))
{
TraceTag(ttidNetcfgBase, "%s: could not locate instance GUID of %S",
__FUNCNAME__, pszComponentId);
}
#endif
}
TraceHr(ttidError, FAL, hr, (S_FALSE == hr), __FUNCNAME__);
return (SUCCEEDED(hr)) ? TRUE : FALSE;
}
//+---------------------------------------------------------------------------
//
// Function: FIsBindingName
//
// Purpose: Returns TRUE if a binding interface is of the specified name.
//
// Arguments:
// pszName [in] Name of the binding interface to check for.
// dwFlags [in] FIBN_ flags
// pncbi [in] Binding interface pointer.
//
// Returns: TRUE if the binding interface is of the specified name.
//
// Author: shaunco 24 Mar 1997
//
// Notes:
//
BOOL
FIsBindingName (
PCWSTR pszName,
DWORD dwFlags,
INetCfgBindingInterface* pncbi)
{
Assert (pszName);
Assert (pncbi);
BOOL fRet = FALSE;
PWSTR pszInterfaceName;
if (SUCCEEDED(pncbi->GetName (&pszInterfaceName)))
{
INT c_cchPrefix = (FIBN_PREFIX & dwFlags) ? lstrlenW (pszName) : -1;
fRet = (2 == CompareStringW (LOCALE_SYSTEM_DEFAULT, 0,
pszName, c_cchPrefix,
pszInterfaceName, c_cchPrefix));
CoTaskMemFree (pszInterfaceName);
}
return fRet;
}
//+---------------------------------------------------------------------------
//
// Function: FIsComponentId
//
// Purpose: Returns TRUE if a component is of the specified id.
//
// Arguments:
// pszComponentId [in] Component Id to check for.
// pncc [in] Component interface pointer.
//
// Returns: TRUE if component is of the specified id.
//
// Author: shaunco 24 Mar 1997
//
// Notes:
//
BOOL
FIsComponentId (
PCWSTR pszComponentId,
INetCfgComponent* pncc)
{
Assert (pszComponentId);
Assert (pncc);
BOOL fRet = FALSE;
PWSTR pszId;
if (SUCCEEDED(pncc->GetId (&pszId)))
{
if (FEqualComponentId (pszComponentId, pszId))
fRet = TRUE;
CoTaskMemFree (pszId);
}
return fRet;
}
//+---------------------------------------------------------------------------
//
// Function: HrAddOrRemoveAdapter
//
// Purpose:
//
// Arguments:
// pnc [in] pointer to an INetCfg object.
// pszComponentId [in] component INF id.
// dwFlags [in]
//
// ARA_ADD : Add the component
// ARA_REMOVE : Remove the component. Cannot be specified
// with ARA_ADD.
// pOboToken [in] If specified, refcount the adapter. This is the
// on behalf of token adding or removing the specified
// component. This allows per-component reference
// counts of another.
// cInstances [in] this specifies how many instances (or references)
// to add or remove.
// ppncc [out] (optional). The newly added component. Can only
// be specified when adding one component.
//
// Returns: S_OK or an error
//
// Author: shaunco 28 Mar 1997
//
// Notes:
//
HRESULT
HrAddOrRemoveAdapter (
INetCfg* pnc,
PCWSTR pszComponentId,
DWORD dwFlags,
OBO_TOKEN* pOboToken,
UINT cInstances,
INetCfgComponent** ppncc)
{
Assert (pnc);
Assert (pszComponentId);
Assert (dwFlags);
Assert (cInstances);
#ifdef DBG
AssertSz ((dwFlags & ARA_ADD) || (dwFlags & ARA_REMOVE),
"Need to add or remove. Can't do neither.");
if (dwFlags & ARA_ADD)
{
AssertSz (!(dwFlags & ARA_REMOVE), "Can't remove AND add.");
}
if (dwFlags & ARA_REMOVE)
{
AssertSz (!(dwFlags & ARA_ADD), "Can't add AND remove.");
}
AssertSz (FImplies(1 != cInstances, NULL == ppncc),
"Can't return ppncc when cInstances is greater than one.");
AssertSz (FImplies(ppncc, 1 == cInstances),
"Can only add one instance when returning ppncc.");
AssertSz (FImplies(ppncc, dwFlags & ARA_ADD),
"Can't return ppncc when removing.");
#endif
// Get the component class object for adapters.
INetCfgClass* pncclass;
HRESULT hr = pnc->QueryNetCfgClass (&GUID_DEVCLASS_NET, IID_INetCfgClass,
reinterpret_cast<void**>(&pncclass));
if (S_OK == hr)
{
INetCfgClassSetup* pncclasssetup;
hr = pncclass->QueryInterface (IID_INetCfgClassSetup,
reinterpret_cast<void**>(&pncclasssetup));
if (S_OK == hr)
{
if (dwFlags & ARA_ADD)
{
// Install the component the specified number of times.
//
while (SUCCEEDED(hr) && cInstances--)
{
hr = pncclasssetup->Install(pszComponentId, pOboToken,
0, 0, NULL, NULL, ppncc );
}
}
else
{
// Remove the component the specified number of times.
//
AssertSz(S_OK == hr, "hr should be S_OK here to make sure the "
"loop is given a chance.");
while (SUCCEEDED(hr) && cInstances)
{
// Find and remove the component.
//
INetCfgComponent* pncc;
hr = pncclass->FindComponent (pszComponentId, &pncc);
if (S_OK == hr)
{
hr = pncclasssetup->DeInstall (pncc,
pOboToken, NULL);
cInstances--;
ReleaseObj (pncc);
}
else if (S_FALSE == hr)
{
// If it wasn't found, get out.
break;
}
}
AssertSz (FImplies(SUCCEEDED(hr), (0 == cInstances)),
"cInstances should be zero. This assert means "
"that we were asked to remove more instances than "
"were installed.");
}
// Normalize the HRESULT.
// Possible values of hr at this point are S_FALSE,
// NETCFG_S_REBOOT, and NETCFG_S_STILL_REFERENCED.
//
if (SUCCEEDED(hr))
{
hr = S_OK;
}
ReleaseObj( pncclasssetup );
}
ReleaseObj (pncclass);
}
TraceHr (ttidError, FAL, hr, FALSE, "HrAddOrRemoveAdapter");
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrFindAndRemoveAllInstancesOfAdapter
//
// Purpose: Remove all instances of the adapter with the specified
// component id.
//
// Arguments:
// pnc [in] INetCfg pointer.
// pszComponentId [in] Component id to search for and remove.
//
// Returns: S_OK or an error code
//
// Author: shaunco 4 Jan 1998
//
// Notes:
//
HRESULT
HrFindAndRemoveAllInstancesOfAdapter (
INetCfg* pnc,
PCWSTR pszComponentId)
{
Assert (pnc);
Assert (pszComponentId);
PCWSTR apszComponentId [1];
apszComponentId[0] = pszComponentId;
HRESULT hr = HrFindAndRemoveAllInstancesOfAdapters (pnc,
1, apszComponentId);
TraceHr (ttidError, FAL, hr, FALSE,
"HrFindAndRemoveAllInstancesOfAdapter");
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrFindAndRemoveAllInstancesOfAdapters
//
// Purpose: Remove all instances of the adapters with the specified
// component ids.
//
// Arguments:
// pnc [in] INetCfg pointer.
// cComponents [in] Count of component ids in the array.
// apszComponentId [in] Array of compoennt ids to search for and
// remove.
//
// Returns: S_OK or an error code.
//
// Author: shaunco 4 Jan 1998
//
// Notes:
//
HRESULT
HrFindAndRemoveAllInstancesOfAdapters (
INetCfg* pnc,
ULONG cComponents,
const PCWSTR* apszComponentId)
{
Assert (pnc);
Assert (cComponents);
Assert (apszComponentId);
// Get the class object for adapters.
INetCfgClass* pncclass;
INetCfgClassSetup* pncclasssetup;
HRESULT hr = pnc->QueryNetCfgClass (&GUID_DEVCLASS_NET,
IID_INetCfgClass,
reinterpret_cast<void**>(&pncclass));
if (S_OK == hr)
{
hr = pncclass->QueryInterface (IID_INetCfgClassSetup,
reinterpret_cast<void**>(&pncclasssetup));
if (S_OK == hr)
{
for (ULONG i = 0; (i < cComponents) && SUCCEEDED(hr); i++)
{
// Find and remove all instances of the component.
INetCfgComponent* pncc;
while ((SUCCEEDED(hr)) &&
(S_OK == (hr = pncclass->FindComponent (
apszComponentId[i], &pncc))))
{
hr = pncclasssetup->DeInstall (pncc, NULL, NULL);
ReleaseObj (pncc);
}
// Normalize the HRESULT.
//
if (SUCCEEDED(hr))
{
hr = S_OK;
}
}
ReleaseObj (pncclasssetup);
}
ReleaseObj (pncclass);
}
TraceHr (ttidError, FAL, hr, FALSE,
"HrFindAndRemoveAllInstancesOfAdapters");
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrFindAndRemoveComponent
//
// Purpose: Find and remove the component with the specified id.
//
// Arguments:
// pnc [in] INetCfg pointer.
// pguidClass [in] Class GUID of the component.
// pszComponentId [in] Component id to search for and remove.
// pOboToken [in] (Optional) If specified, remove on behalf of.
//
// Returns: S_OK, NETCFG_S_STILL_REFERENCED, or an error code.
//
// Author: shaunco 4 Jan 1998
//
// Notes:
//
HRESULT
HrFindAndRemoveComponent (
INetCfg* pnc,
const GUID* pguidClass,
PCWSTR pszComponentId,
OBO_TOKEN* pOboToken)
{
Assert (pnc);
Assert (pguidClass);
Assert (pszComponentId);
AssertSz (GUID_DEVCLASS_NET != *pguidClass,
"Don't use this to remove adapters.");
// Get the component class object.
//
INetCfgClass* pncclass;
HRESULT hr = pnc->QueryNetCfgClass (pguidClass, IID_INetCfgClass,
reinterpret_cast<void**>(&pncclass));
if (SUCCEEDED(hr))
{
// Find the component to remove.
//
INetCfgComponent* pnccRemove;
hr = pncclass->FindComponent (pszComponentId, &pnccRemove);
if (S_OK == hr)
{
INetCfgClassSetup* pncclasssetup;
hr = pncclass->QueryInterface (IID_INetCfgClassSetup,
reinterpret_cast<void**>(&pncclasssetup));
if (SUCCEEDED(hr))
{
hr = pncclasssetup->DeInstall (pnccRemove, pOboToken, NULL);
ReleaseObj (pncclasssetup);
}
ReleaseObj (pnccRemove);
}
else if (S_FALSE == hr)
{
hr = S_OK;
}
ReleaseObj (pncclass);
}
TraceHr (ttidError, FAL, hr,
(NETCFG_S_REBOOT == hr) || (NETCFG_S_STILL_REFERENCED == hr),
"HrFindAndRemoveComponent");
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrFindAndRemoveComponents
//
// Purpose: Find and remove the components with the specified ids.
//
// Arguments:
// pnc [in] INetCfg pointer.
// cComponents [in] Count of components in the array.
// apguidClass [in] Array of class GUIDs corresponding to the
// array of component ids.
// apszComponentId [in] Array of component ids to search for and
// remove.
// pOboToken [in] (Optional) If specified, remove on behalf of.
//
// Returns: S_OK, NETCFG_S_STILL_REFERENCED, or an error code.
//
// Author: shaunco 4 Jan 1998
//
// Notes:
//
HRESULT
HrFindAndRemoveComponents (
INetCfg* pnc,
ULONG cComponents,
const GUID** apguidClass,
const PCWSTR* apszComponentId,
OBO_TOKEN* pOboToken)
{
Assert (pnc);
Assert (cComponents);
Assert (apguidClass);
Assert (apszComponentId);
HRESULT hr = S_OK;
for (ULONG i = 0; (i < cComponents) && SUCCEEDED(hr); i++)
{
hr = HrFindAndRemoveComponent (pnc, apguidClass[i],
apszComponentId[i], pOboToken);
}
TraceHr (ttidError, FAL, hr,
(NETCFG_S_REBOOT == hr) || (NETCFG_S_STILL_REFERENCED == hr),
"HrFindAndRemoveComponents");
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrFindAndRemoveComponentsOboComponent
//
// Purpose: Remove multiple components on behalf of one component.
//
// Arguments:
// pnc [in] pointer to an INetCfg object.
// cComponents [in] count of class guid pointers and component id
// pointers.
// apguidClass [in] array of class guid pointers.
// apszId [in] array of component id pointers.
// pnccObo [in] the component requesting the remove. (i.e. the
// "on behalf of" component.)
//
// Returns: S_OK, NETCFG_S_STILL_REFERENCED, or an error code.
//
// Author: shaunco 13 Apr 1997
//
// Notes:
//
HRESULT
HrFindAndRemoveComponentsOboComponent (
INetCfg* pnc,
ULONG cComponents,
const GUID** apguidClass,
const PCWSTR* apszComponentId,
INetCfgComponent* pnccObo)
{
Assert (pnc);
Assert (cComponents);
Assert (apguidClass);
Assert (apszComponentId);
Assert (pnccObo);
// Make an "on behalf of" token for the requesting component.
//
OBO_TOKEN OboToken;
ZeroMemory (&OboToken, sizeof(OboToken));
OboToken.Type = OBO_COMPONENT;
OboToken.pncc = pnccObo;
HRESULT hr = HrFindAndRemoveComponents (pnc, cComponents,
apguidClass, apszComponentId, &OboToken);
TraceHr (ttidError, FAL, hr,
(NETCFG_S_REBOOT == hr) || (NETCFG_S_STILL_REFERENCED == hr),
"HrFindAndRemoveComponentsOboComponent");
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrFindAndRemoveComponentsOboUser
//
// Purpose: Remove multiple components on behalf of one component.
//
// Arguments:
// pnc [in] pointer to an INetCfg object.
// cComponents [in] count of class guid pointers and component id
// pointers.
// apguidClass [in] array of class guid pointers.
// apszId [in] array of component id pointers.
//
// Returns: S_OK, NETCFG_S_STILL_REFERENCED, or an error code.
//
// Author: shaunco 13 Apr 1997
//
// Notes:
//
HRESULT
HrFindAndRemoveComponentsOboUser (
INetCfg* pnc,
ULONG cComponents,
const GUID** apguidClass,
const PCWSTR* apszComponentId)
{
Assert (pnc);
Assert (cComponents);
Assert (apguidClass);
Assert (apszComponentId);
// Make an "on behalf of" token for the user.
//
OBO_TOKEN OboToken;
ZeroMemory (&OboToken, sizeof(OboToken));
OboToken.Type = OBO_USER;
HRESULT hr = HrFindAndRemoveComponents (pnc, cComponents,
apguidClass, apszComponentId, &OboToken);
TraceHr (ttidError, FAL, hr,
(NETCFG_S_REBOOT == hr) || (NETCFG_S_STILL_REFERENCED == hr),
"HrFindAndRemoveComponentsOboUser");
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrFindComponents
//
// Purpose: Find multiple INetCfgComponents with one call. This makes
// the error handling associated with multiple calls to
// QueryNetCfgClass and Find much easier.
//
// Arguments:
// pnc [in] pointer to INetCfg object
// cComponents [in] count of class guid pointers, component id
// pointers, and INetCfgComponent output pointers.
// apguidClass [in] array of class guid pointers.
// apszComponentId [in] array of component id pointers.
// apncc [out] array of returned INetCfgComponet pointers.
//
// Returns: S_OK or an error code.
//
// Author: shaunco 22 Mar 1997
//
// Notes: cComponents is the count of pointers in all three arrays.
// S_OK will still be returned even if no components were
// found! This is by design.
//
HRESULT
HrFindComponents (
INetCfg* pnc,
ULONG cComponents,
const GUID** apguidClass,
const PCWSTR* apszComponentId,
INetCfgComponent** apncc)
{
Assert (pnc);
Assert (cComponents);
Assert (apguidClass);
Assert (apszComponentId);
Assert (apncc);
// Initialize the output parameters.
//
ZeroMemory (apncc, cComponents * sizeof(*apncc));
// Find all of the components requested.
// Variable initialization is important here.
HRESULT hr = S_OK;
ULONG i;
for (i = 0; (i < cComponents) && SUCCEEDED(hr); i++)
{
// Get the class object for this component.
INetCfgClass* pncclass;
hr = pnc->QueryNetCfgClass (apguidClass[i], IID_INetCfgClass,
reinterpret_cast<void**>(&pncclass));
if (SUCCEEDED(hr))
{
// Find the component.
hr = pncclass->FindComponent (apszComponentId[i], &apncc[i]);
AssertSz (SUCCEEDED(hr), "pncclass->Find failed.");
ReleaseObj (pncclass);
}
}
// On any error, release what we found and set the output to NULL.
if (FAILED(hr))
{
for (i = 0; i < cComponents; i++)
{
ReleaseObj (apncc[i]);
apncc[i] = NULL;
}
}
// Otherwise, normalize the HRESULT. (i.e. don't return S_FALSE)
else
{
hr = S_OK;
}
TraceHr (ttidError, FAL, hr, FALSE, "HrFindComponents");
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrGetBindingInterfaceComponents
//
// Purpose: Get both upper and lower components involved in a
// binding interface.
//
// Arguments:
// pncbi [in] binding interface.
// ppnccUpper [out] output upper component.
// ppnccLower [out] output lower compoenet.
//
// Returns: S_OK or an error code.
//
// Author: shaunco 18 Apr 1997
//
// Notes:
//
HRESULT
HrGetBindingInterfaceComponents (
INetCfgBindingInterface* pncbi,
INetCfgComponent** ppnccUpper,
INetCfgComponent** ppnccLower)
{
Assert (pncbi);
Assert (ppnccUpper);
Assert (ppnccLower);
// Initialize the output parameters.
*ppnccUpper = NULL;
*ppnccLower = NULL;
INetCfgComponent* pnccUpper;
HRESULT hr = pncbi->GetUpperComponent (&pnccUpper);
if (SUCCEEDED(hr))
{
INetCfgComponent* pnccLower;
hr = pncbi->GetLowerComponent (&pnccLower);
if (SUCCEEDED(hr))
{
*ppnccUpper = pnccUpper;
*ppnccLower = pnccLower;
}
else
{
// Rather than AddRef this in the above SUCCEEDED block followed
// by the normal unconditional Release, just Release here in
// the case of failure to get the lower component.
ReleaseObj (pnccUpper);
}
}
TraceHr (ttidError, FAL, hr, FALSE, "HrGetBindingInterfaceComponents");
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrInstallComponent
//
// Purpose: Install the component with a specified id.
//
// Arguments:
// pnc [in] INetCfg pointer.
// pnip [in] (Optional) If specified, perform the installation
// using the answer file.
// pguidClass [in] Class guid of the component to install.
// pszComponentId [in] Component id to install.
// pOboToken [in] (Optional) If specified, perform the installation
// on behalf of this token.
// ppncc [out] (Optional) Returned component that was
// installed.
//
// Returns: S_OK or an error code.
//
// Author: shaunco 4 Jan 1998
//
// Notes:
//
HRESULT
HrInstallComponent (
INetCfg* pnc,
const NETWORK_INSTALL_PARAMS* pnip,
const GUID* pguidClass,
PCWSTR pszComponentId,
OBO_TOKEN* pOboToken,
INetCfgComponent** ppncc)
{
Assert (pnc);
Assert (pszComponentId);
// Initialize output parameter.
//
if (ppncc)
{
*ppncc = NULL;
}
// Get the class setup object.
//
INetCfgClassSetup* pncclasssetup;
HRESULT hr = pnc->QueryNetCfgClass (pguidClass, IID_INetCfgClassSetup,
reinterpret_cast<void**>(&pncclasssetup));
if (SUCCEEDED(hr))
{
if (pnip)
{
hr = pncclasssetup->Install (
pszComponentId,
pOboToken,
pnip->dwSetupFlags,
pnip->dwUpgradeFromBuildNo,
pnip->pszAnswerFile,
pnip->pszAnswerSection,
ppncc);
}
else
{
hr = pncclasssetup->Install (pszComponentId,
pOboToken, 0, 0, NULL, NULL, ppncc);
}
ReleaseObj (pncclasssetup);
}
TraceHr (ttidError, FAL, hr, (NETCFG_S_REBOOT == hr),
"HrInstallComponent (%S)", pszComponentId);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrInstallComponents
//
// Purpose: Install the components with the specified ids.
//
// Arguments:
// pnc [in] INetCfg pointer.
// pnip [in] (Optional) If specified, perform the installation
// using the answer file.
// cComponents [in] Count of components in the arrays.
// apguidClass [in] Array of class guids for the specified components.
// apszComponentId [in] Array of component ids to install.
// pOboToken [in] (Optional) If specified, perform the installation
// on behalf of this token.
//
// Returns: S_OK or an error code.
//
// Author: shaunco 4 Jan 1998
//
// Notes:
//
HRESULT
HrInstallComponents (
INetCfg* pnc,
const NETWORK_INSTALL_PARAMS* pnip,
ULONG cComponents,
const GUID** apguidClass,
const PCWSTR* apszComponentId,
OBO_TOKEN* pOboToken)
{
Assert (pnc);
Assert (cComponents);
Assert (apguidClass);
Assert (apszComponentId);
HRESULT hr = S_OK;
for (ULONG i = 0; (i < cComponents) && SUCCEEDED(hr); i++)
{
hr = HrInstallComponent (pnc, pnip,
apguidClass[i], apszComponentId[i], pOboToken, NULL);
}
TraceHr (ttidError, FAL, hr, (NETCFG_S_REBOOT == hr),
"HrInstallComponents");
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrInstallComponentsOboComponent
//
// Purpose: Install multiple components on behalf of one component.
//
// Arguments:
// pnc [in] pointer to an INetCfg object.
// pnip [in] (Optional) pointer to network install parameters.
// If non-NULL, a network install is performed,
// otherwise a normal install is performed.
// cComponents [in] count of class guid pointers and component id
// pointers.
// apguidClass [in] array of class guid pointers.
// apszComponentId [in] array of component id pointers.
// pnccObo [in] the component requesting the install. (i.e. the
// "on behalf of" component.)
//
// Returns: S_OK or an error code.
//
// Author: shaunco 13 Apr 1997
//
// Notes:
//
HRESULT
HrInstallComponentsOboComponent (
INetCfg* pnc,
const NETWORK_INSTALL_PARAMS* pnip,
ULONG cComponents,
const GUID** apguidClass,
const PCWSTR* apszComponentId,
INetCfgComponent* pnccObo)
{
Assert (pnccObo);
// Make an "on behalf of" token for the requesting component.
//
OBO_TOKEN OboToken;
ZeroMemory (&OboToken, sizeof(OboToken));
OboToken.Type = OBO_COMPONENT;
OboToken.pncc = pnccObo;
HRESULT hr = HrInstallComponents (pnc, pnip, cComponents, apguidClass,
apszComponentId, &OboToken);
TraceHr (ttidError, FAL, hr, (NETCFG_S_REBOOT == hr),
"HrInstallComponentsOboComponent");
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrInstallComponentsOboUser
//
// Purpose: Install multiple components on behalf of the user.
//
// Arguments:
// pnc [in] INetCfg pointer.
// pnip [in] (Optional) If specified, perform the installation
// using the answer file.
// cComponents [in] Count of components in the arrays.
// apguidClass [in] Array of class guids for the specified components.
// apszComponentId [in] Array of component ids to install.
//
// Returns:
//
// Author: shaunco 4 Jan 1998
//
// Notes:
//
HRESULT
HrInstallComponentsOboUser (
INetCfg* pnc,
const NETWORK_INSTALL_PARAMS* pnip,
ULONG cComponents,
const GUID** apguidClass,
const PCWSTR* apszComponentId)
{
// Make an "on behalf of" token for the user.
//
OBO_TOKEN OboToken;
ZeroMemory (&OboToken, sizeof(OboToken));
OboToken.Type = OBO_USER;
HRESULT hr = HrInstallComponents (pnc, pnip, cComponents, apguidClass,
apszComponentId, &OboToken);
TraceHr (ttidError, FAL, hr, (NETCFG_S_REBOOT == hr),
"HrInstallComponentsOboUser");
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrInstallComponentOboComponent
//
// Purpose: Installs a component on behalf of another. If the component
// is already installed, it reference count is incremented on
// behalf of the component doing the install. When one
// component calls this function to install another, it is
// saying that it has a depencency on the component being
// installed. This dependency will prevent even the user from
// removing the component.
//
// Arguments:
// pnc [in] pointer to an INetCfg object.
// pnip [in] (Optional) pointer to network install parameters.
// If non-NULL, a network install is performed,
// otherwise a normal install is performed.
// rguid [in] class GUID of the component being installed.
// pszComponentId [in] component INF id of the component being installed.
// pnccObo [in] the component requesting the install. (i.e. the
// "on behalf of" component.)
// ppncc [out] (Optional) set on return to the previously
// installed component or the one that was installed.
//
// Returns: S_OK or an error.
//
// Author: shaunco 7 Apr 1997
//
// Notes:
//
HRESULT
HrInstallComponentOboComponent (
INetCfg* pnc,
const NETWORK_INSTALL_PARAMS* pnip,
const GUID& rguid,
PCWSTR pszComponentId,
INetCfgComponent* pnccObo,
INetCfgComponent** ppncc)
{
Assert (pnc);
Assert (pszComponentId);
Assert (pnccObo);
// Initialize output parameter.
//
if (ppncc)
{
*ppncc = NULL;
}
// Make an "on behalf of" token for the requesting component.
//
OBO_TOKEN OboToken;
ZeroMemory (&OboToken, sizeof(OboToken));
OboToken.Type = OBO_COMPONENT;
OboToken.pncc = pnccObo;
HRESULT hr = HrInstallComponent (pnc, pnip, &rguid, pszComponentId,
&OboToken, ppncc);
TraceHr (ttidError, FAL, hr, (NETCFG_S_REBOOT == hr),
"HrInstallComponentOboComponent");
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrInstallComponentOboSoftware
//
// Purpose: Installs a component on behalf of a piece of software.
// If the component is already installed, it's reference count
// is incremented on behalf of the indicated software piece.
// This is useful for a component to call
// when it is installing another component as a convienience for
// the user. The user can then remove the component with no
// ill-effects for the component that called this function.
//
// Arguments:
// pnc [in] pointer to an INetCfg object.
// pnip [in] (Optional) pointer to network install parameters.
// If non-NULL, a network install is performed,
// otherwise a normal install is performed.
// rguid [in] class GUID of the component being installed.
// pszComponentId [in] component INF id of the component being installed.
// pszManufacturer [in] Manufacturer name of software.
// pszProduct [in] Product name of software.
// pszDisplayName [in] Full display name of software.
// ppncc [out] (Optional) set on return to the previously
// installed component or the one that was installed.
//
// Returns:
//
// Author: danielwe 5 May 1997
//
// Notes:
//
HRESULT
HrInstallComponentOboSoftware (
INetCfg* pnc,
const NETWORK_INSTALL_PARAMS* pnip,
const GUID& rguid,
PCWSTR pszComponentId,
PCWSTR pszManufacturer,
PCWSTR pszProduct,
PCWSTR pszDisplayName,
INetCfgComponent** ppncc)
{
Assert (pnc);
Assert (pszComponentId);
Assert (pszManufacturer);
Assert (pszDisplayName);
Assert (pszProduct);
AssertSz (GUID_DEVCLASS_NET != rguid, "Don't use this to install adapters.");
// Initialize output parameter.
//
if (ppncc)
{
*ppncc = NULL;
}
// Make an "on behalf of" token for the software.
//
OBO_TOKEN OboToken;
ZeroMemory (&OboToken, sizeof(OboToken));
OboToken.Type = OBO_SOFTWARE;
OboToken.pszwManufacturer = pszManufacturer;
OboToken.pszwProduct = pszProduct;
OboToken.pszwDisplayName = pszDisplayName;
HRESULT hr = HrInstallComponent (pnc, pnip, &rguid, pszComponentId,
&OboToken, ppncc);
TraceHr (ttidError, FAL, hr, (NETCFG_S_REBOOT == hr),
"HrInstallComponentOboSoftware");
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrInstallComponentOboUser
//
// Purpose: Installs a component on behalf of the user. If the component
// is already installed, it reference count is incremented on
// behalf of the user. This is useful for a component to call
// when it is installing another component as a convienience for
// the user. The user can then remove the component with no
// ill-effects for the component that called this function.
//
// Arguments:
// pnc [in] pointer to an INetCfg object.
// pnip [in] (Optional) pointer to network install parameters.
// If non-NULL, a network install is performed,
// otherwise a normal install is performed.
// rguid [in] class GUID of the component being installed.
// pszComponentId [in] component INF id of the component being installed.
// ppncc [out] (Optional) set on return to the previously
// installed component or the one that was installed.
//
// Returns: S_OK or an error.
//
// Author: shaunco 7 Apr 1997
//
// Notes:
//
HRESULT
HrInstallComponentOboUser (
INetCfg* pnc,
const NETWORK_INSTALL_PARAMS* pnip,
const GUID& rguid,
PCWSTR pszComponentId,
INetCfgComponent** ppncc)
{
Assert (pnc);
Assert (&rguid);
Assert (pszComponentId);
AssertSz (GUID_DEVCLASS_NET != rguid, "Don't use this to install adapters.");
// Initialize output parameter.
//
if (ppncc)
{
*ppncc = NULL;
}
// Make an "on behalf of" token for the user.
//
OBO_TOKEN OboToken;
ZeroMemory (&OboToken, sizeof(OboToken));
OboToken.Type = OBO_USER;
HRESULT hr = HrInstallComponent (pnc, pnip, &rguid, pszComponentId,
&OboToken, ppncc);
TraceHr (ttidError, FAL, hr, (NETCFG_S_REBOOT == hr),
"HrInstallComponentOboUser");
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrInstallRasIfNeeded
//
// Purpose: Install RAS services on behalf of the user. No need to
// check first as we install on behalf of the user which is
// implicilty checked.
//
// Arguments:
// pnc [in] INetCfg pointer to use
//
// Returns: S_OK or an error code.
//
// Author: shaunco 30 Aug 1997
//
// Notes:
// (shaunco) 10 Sep 1997: Don't install RAS Server for Beta1.
// DHCP addresses get eaten up too quickly. For Beta2, it will be
// installed but disabled.
//
// (shaunco) 20 Dec 1997: We used to install RAS Server only on NTS.
// We now install it always but its set to not start automatically.
//
HRESULT
HrInstallRasIfNeeded (
INetCfg* pnc)
{
Assert (pnc);
static const GUID* c_apguidInstalledComponentClasses [] =
{
&GUID_DEVCLASS_NETSERVICE, // RasCli
&GUID_DEVCLASS_NETSERVICE, // RasSrv
};
static const PCWSTR c_apszInstalledComponentIds [] =
{
c_szInfId_MS_RasCli,
c_szInfId_MS_RasSrv,
};
HRESULT hr = HrInstallComponentsOboUser (pnc, NULL,
celems (c_apguidInstalledComponentClasses),
c_apguidInstalledComponentClasses,
c_apszInstalledComponentIds);
TraceHr (ttidError, FAL, hr, (NETCFG_S_REBOOT == hr),
"HrInstallRasIfNeeded");
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrQueryNotifyObject
//
// Purpose: Helper function to call QueryNotifyObject given an
// INetCfgComponent. (Saves the intermediate QI.)
//
// Arguments:
// pncc [in] INetCfgComponent to call QueryNotifyObject on.
// riid [in] Requested interface identifier.
// ppvObject [out] Address of pointer to return the requested interface.
//
// Returns: S_OK or an error code.
//
// Author: shaunco 2 Sep 1998
//
// Notes:
//
HRESULT
HrQueryNotifyObject (
INetCfgComponent* pncc,
REFIID riid,
VOID** ppvObject)
{
Assert (pncc);
Assert (ppvObject);
// Initialize the output parameter.
//
*ppvObject = NULL;
// First, QI for the component private interface.
//
INetCfgComponentPrivate* pPrivate;
HRESULT hr = pncc->QueryInterface(
IID_INetCfgComponentPrivate,
reinterpret_cast<VOID**>(&pPrivate));
if (SUCCEEDED(hr))
{
// Now query the notify object for the requested interface.
//
hr = pPrivate->QueryNotifyObject (riid, ppvObject);
ReleaseObj (pPrivate);
}
TraceHr (ttidError, FAL, hr, FALSE, "HrQueryNotifyObject");
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrRemoveComponent
//
// Purpose: Remove the specified component.
//
// Arguments:
// pnc [in] INetCfg pointer.
// pnccToRemove [in] Component to remove.
// pOboToken [in] (Optional) If specified, remove the component
// on behalf of this token.
// pmszRefs [out] (Optional) Returns Multi-Sz of components that
// still reference this one. NOTE: This will be NULL
// if the return value is not
// NETCFG_S_STILL_REFERENCED
//
// Returns: S_OK, NETCFG_S_STILL_REFERENCED, or an error code.
//
// Author: shaunco 4 Jan 1998
//
// Notes:
//
HRESULT
HrRemoveComponent (
INetCfg* pnc,
INetCfgComponent* pnccToRemove,
OBO_TOKEN* pOboToken,
PWSTR * pmszRefs)
{
Assert (pnc);
Assert (pnccToRemove);
// Get the class setup interface for this component.
//
GUID guidClass;
HRESULT hr = pnccToRemove->GetClassGuid (&guidClass);
if (SUCCEEDED(hr))
{
// Use the class setup interface to remove the component.
//
INetCfgClassSetup* pSetup;
hr = pnc->QueryNetCfgClass (&guidClass,
IID_INetCfgClassSetup,
reinterpret_cast<void**>(&pSetup));
if (SUCCEEDED(hr))
{
hr = pSetup->DeInstall (pnccToRemove, pOboToken, pmszRefs);
ReleaseObj (pSetup);
}
}
TraceHr (ttidError, FAL, hr,
(NETCFG_S_REBOOT == hr) || (NETCFG_S_STILL_REFERENCED == hr),
"HrRemoveComponent");
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrRemoveComponentOboComponent
//
// Purpose: Removes a component previously installed by another.
// Effectively balances a call to HrInstallComponentOboComponent().
// The reference count of the component is decremented and,
// if it is zero, the component is removed from the system.
//
// Arguments:
// pnc [in] pointer to an INetCfg object.
// rguidClass [in] class GUID of the component being removed.
// pszComponentId [in] component INF id of the component being removed.
// pnccObo [in] the component requesting the removal.
//
// Returns: S_OK, NETCFG_S_STILL_REFERENCED or an error.
//
// Author: shaunco 7 Apr 1997
//
// Notes:
//
HRESULT
HrRemoveComponentOboComponent (
INetCfg* pnc,
const GUID& rguidClass,
PCWSTR pszComponentId,
INetCfgComponent* pnccObo)
{
// Make an "on behalf of" token for the requesting component.
//
OBO_TOKEN OboToken;
ZeroMemory (&OboToken, sizeof(OboToken));
OboToken.Type = OBO_COMPONENT;
OboToken.pncc = pnccObo;
HRESULT hr = HrFindAndRemoveComponent (pnc, &rguidClass, pszComponentId,
&OboToken);
TraceHr (ttidError, FAL, hr,
(NETCFG_S_REBOOT == hr) || (NETCFG_S_STILL_REFERENCED == hr),
"HrRemoveComponentOboComponent");
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrRemoveComponentOboSoftware
//
// Purpose: Removes a component previously installed by some software
// entity. Effectively balances a call to
// HrAddComponentOboSoftware(). The reference count of the
// component is decremented and, if it is zero, the component
// is removed from the system.
//
// Arguments:
// pnc [in] pointer to an INetCfg object.
// rguidClass [in] class GUID of the component being removed.
// pszComponentId [in] component INF id of the component being removed.
// pszManufacturer [in] Manufacturer name of software.
// pszProduct [in] Product name of software.
// pszDisplayName [in] Full display name of software.
// pnccObo [in] the component requesting the removal.
//
// Returns: S_OK, NETCFG_S_STILL_REFERENCED or an error.
//
// Author: jeffspr 13 Jun 1997
//
// Notes:
//
HRESULT
HrRemoveComponentOboSoftware (
INetCfg* pnc,
const GUID& rguidClass,
PCWSTR pszComponentId,
PCWSTR pszManufacturer,
PCWSTR pszProduct,
PCWSTR pszDisplayName)
{
// Make an "on behalf of" token for the software.
//
OBO_TOKEN OboToken;
ZeroMemory (&OboToken, sizeof(OboToken));
OboToken.Type = OBO_SOFTWARE;
OboToken.pszwManufacturer = pszManufacturer;
OboToken.pszwProduct = pszProduct;
OboToken.pszwDisplayName = pszDisplayName;
HRESULT hr = HrFindAndRemoveComponent (pnc, &rguidClass, pszComponentId,
&OboToken);
TraceHr (ttidError, FAL, hr,
(NETCFG_S_REBOOT == hr) || (NETCFG_S_STILL_REFERENCED == hr),
"HrRemoveComponentOboSoftware");
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrRemoveComponentOboUser
//
// Purpose: Removes a component previously installed by the user.
// Effectively balances a call to HrAddComponentOboUser().
// The reference count of the component is decremented and,
// if it is zero, the component is removed from the system.
//
// Arguments:
// pnc [in] pointer to an INetCfg object.
// rguidClass [in] class GUID of the component being removed.
// pszComponentId [in] component INF id of the component being removed.
//
// Returns: S_OK, NETCFG_S_STILL_REFERENCED or an error.
//
// Author: shaunco 7 Apr 1997
//
// Notes:
//
HRESULT
HrRemoveComponentOboUser (
INetCfg* pnc,
const GUID& rguidClass,
PCWSTR pszComponentId)
{
// Make an "on behalf of" token for the user.
//
OBO_TOKEN OboToken;
ZeroMemory (&OboToken, sizeof(OboToken));
OboToken.Type = OBO_USER;
HRESULT hr = HrFindAndRemoveComponent (pnc, &rguidClass, pszComponentId,
&OboToken);
TraceHr (ttidError, FAL, hr,
(NETCFG_S_REBOOT == hr) || (NETCFG_S_STILL_REFERENCED == hr),
"HrRemoveComponentOboUser");
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrGetLastComponentAndInterface
//
// Purpose: This function enumerates a binding path, returns the last
// component on the path and optionally return the last binding
// interface name in this path.
//
// Arguments:
// pncbp [in] The INetCfgBindingPath *
// ppncc [out] The INetCfgComponent * of the last component on the path
// ppszInterfaceName [out] The interface name of the last binding interface of the path
//
// Returns: S_OK, or an error.
//
// Author: tongl 5 Dec 1997
//
// Notes:
//
HRESULT
HrGetLastComponentAndInterface (
INetCfgBindingPath* pncbp,
INetCfgComponent** ppncc,
PWSTR* ppszInterfaceName)
{
Assert(pncbp);
// Initialize output parameters.
//
*ppncc = NULL;
if (ppszInterfaceName)
{
*ppszInterfaceName = NULL;
}
// Enumerate binding interfaces and keep track of
// the last interface.
//
HRESULT hr = S_OK;
CIterNetCfgBindingInterface ncbiIter(pncbp);
INetCfgBindingInterface* pncbi;
INetCfgBindingInterface* pncbiLast = NULL;
while(SUCCEEDED(hr) && (hr = ncbiIter.HrNext(&pncbi)) == S_OK)
{
ReleaseObj (pncbiLast);
pncbiLast = pncbi;
}
if (S_FALSE == hr) // we got to the end of the loop
{
hr = S_OK;
Assert (pncbiLast);
INetCfgComponent* pnccLowerComponent;
hr = pncbiLast->GetLowerComponent(&pnccLowerComponent);
if (S_OK == hr)
{
// Get the name of the interface if requested.
//
if (ppszInterfaceName)
{
hr = pncbiLast->GetName(ppszInterfaceName);
}
// If we've succeded everything, (including the optional
// return of the interface name above) then assign and addref
// the output interface.
//
if (S_OK == hr)
{
AddRefObj (pnccLowerComponent);
*ppncc = pnccLowerComponent;
}
// Important to release our use of this interface in case
// we failed and didn't assign it as an output parameter.
//
ReleaseObj (pnccLowerComponent);
}
}
// Don't forget to release the binding interface itself.
//
ReleaseObj (pncbiLast);
TraceHr (ttidError, FAL, hr, FALSE, "HrGetLastComponentAndInterface");
return hr;
}