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