//+--------------------------------------------------------------------------- // // 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 #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_FPNW[]; 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_RSVP[]; 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_FPNW, &GUID_DEVCLASS_NETSERVICE, L"netsfn.inf" }, { c_szInfId_MS_GPC, &GUID_DEVCLASS_NET, L"netgpc.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_RSVP, &GUID_DEVCLASS_NETSERVICE, L"netrsvp.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(NCompareComponentIds); return static_cast (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(&pncclass)); if (S_OK == hr) { INetCfgClassSetup* pncclasssetup; hr = pncclass->QueryInterface (IID_INetCfgClassSetup, reinterpret_cast(&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(&pncclass)); if (S_OK == hr) { hr = pncclass->QueryInterface (IID_INetCfgClassSetup, reinterpret_cast(&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(&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(&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(&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(&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(&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(&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; }