|
|
#include <pch.h>
#pragma hdrstop
#include "persist.h"
#include "ncreg.h"
#include "ncsetup.h"
#include "util.h"
HRESULT HrAddOrRemoveWinsockDependancy( IN HINF hinfInstallFile, IN PCWSTR pszSectionName);
HRESULT HrLoadAndAddComponentFromInstanceKey ( IN HKEY hkey, IN const GUID* pInstanceGuid, IN NETCLASS Class, IN PCWSTR pszPnpId OPTIONAL, IN OUT CNetConfig* pNetConfig) { HRESULT hr; BASIC_COMPONENT_DATA Data; CComponent* pComponent; WCHAR szInfId [_MAX_PATH]; WCHAR szMiniportId [_MAX_PATH]; ULONG cbInfId;
Assert (hkey); Assert (pInstanceGuid); Assert (FIsValidNetClass (Class)); Assert (FImplies(pszPnpId, *pszPnpId)); Assert (pNetConfig);
ZeroMemory (&Data, sizeof(Data));
hr = HrRegQueryDword (hkey, L"Characteristics", &Data.dwCharacter); if (S_OK == hr) { // If the component is a filter, copy Ndi\MiniportId to
// Ndi\FilterDeviceInfId.
//
if (Data.dwCharacter & NCF_FILTER) { HKEY hkeyNdi;
hr = HrRegOpenKeyEx ( hkey, L"Ndi", KEY_READ | KEY_WRITE, &hkeyNdi);
if (S_OK == hr) { HKEY hkeyInterfaces; DWORD cbMiniportId = sizeof(szMiniportId);
hr = HrRegQuerySzBuffer ( hkeyNdi, L"MiniportId", szMiniportId, &cbMiniportId);
if (S_OK == hr) { (VOID) HrRegSetSz ( hkeyNdi, L"FilterDeviceInfId", szMiniportId); }
if (FInSystemSetup()) { // Need to update LowerExclude for filters (the only one
// being PSched) so we prevent PSched from binding to
// every adapter on the machine. This only needs to
// happen during GUI setup and when we detect no Config
// binary because this happens way before INFs get re-run.)
//
hr = HrRegOpenKeyEx ( hkeyNdi, L"Interfaces", KEY_WRITE, &hkeyInterfaces);
if (S_OK == hr) { (VOID) HrRegSetSz ( hkeyInterfaces, L"LowerExclude", L"ndiscowan, ndiswan, ndiswanasync, " L"ndiswanipx, ndiswannbf");
RegCloseKey (hkeyInterfaces); } }
RegCloseKey (hkeyNdi); hr = S_OK; } }
cbInfId = sizeof(szInfId); hr = HrRegQuerySzBuffer (hkey, L"ComponentId", szInfId, &cbInfId); if (S_OK == hr) { // Wanarp needs its refcounts key deleted in case we are
// loaded before netupgrd.inf is run.
//
if (0 == _wcsicmp(L"ms_wanarp", szInfId)) { (VOID)HrRegDeleteKey (hkey, L"RefCounts"); }
Data.InstanceGuid = *pInstanceGuid; Data.Class = Class; Data.pszInfId = szInfId; Data.pszPnpId = pszPnpId;
// It is important to make sure we can load the external data
// for two reasons:
// 1) If we have a failure reading critical data that we
// need in order to function, we want to know about it
// now, before we add it to the component list.
// 2) For filter devices which will be subsequently upgraded,
// we need to search for specific components by BindForm
// and BindName which are external data loaded by the
// following call.
//
hr = CComponent::HrCreateInstance ( &Data, CCI_ENSURE_EXTERNAL_DATA_LOADED, NULL, &pComponent); if (S_OK == hr) { // Add the component and the stack entries, but don't
// send any notifications to notify objects.
//
hr = pNetConfig->Core.HrAddComponentToCore ( pComponent, INS_SORTED); } } }
TraceHr (ttidError, FAL, hr, FALSE, "HrLoadAndAddComponentFromInstanceKey"); return hr; }
BOOL FUpgradeFilterDeviceInstanceKey ( IN CNetConfig* pNetConfig, IN HKEY hkeyInstance, IN PCWSTR pszFilterName) { CComponent* pFilter;
// The new binding engine uses FilterInfId located in under the instance
// key instead of FilterName under Ndi.
//
pFilter = pNetConfig->Core.Components.PFindComponentByBindForm ( NC_NETSERVICE, pszFilterName);
if (pFilter) { (VOID) HrRegSetSz (hkeyInstance, L"FilterInfId", pFilter->m_pszInfId);
return TRUE; } return FALSE; }
HRESULT HrLoadComponentReferencesFromLegacy ( IN OUT CNetConfig* pNetConfig) { HRESULT hr = S_OK; CComponentList::iterator iter; CComponent* pComponent; HKEY hkeyInstance;
Assert (pNetConfig);
for (iter = pNetConfig->Core.Components.begin(); iter != pNetConfig->Core.Components.end(); iter++) { pComponent = *iter; Assert (pComponent);
hr = pComponent->HrOpenInstanceKey (KEY_READ, &hkeyInstance, NULL, NULL);
if (S_OK == hr) { HKEY hkeyRefCounts;
hr = HrRegOpenKeyEx (hkeyInstance, L"RefCounts", KEY_READ, &hkeyRefCounts);
if (S_OK == hr) { DWORD dwIndex; WCHAR szValueName [_MAX_PATH]; DWORD cchValueName; DWORD dwType; DWORD dwRefCount; DWORD cbData; CComponent* pRefdByComponent; GUID InstanceGuid;
for (dwIndex = 0; S_OK == hr; dwIndex++) { cchValueName = celems(szValueName); cbData = sizeof(dwRefCount);
hr = HrRegEnumValue (hkeyRefCounts, dwIndex, szValueName, &cchValueName, &dwType, (LPBYTE)&dwRefCount, &cbData);
if (S_OK == hr) { if (0 == _wcsicmp (L"User", szValueName)) { hr = pComponent->Refs.HrAddReferenceByUser (); } else if ((L'{' == *szValueName) && (S_OK == IIDFromString (szValueName, &InstanceGuid)) && (NULL != (pRefdByComponent = pNetConfig->Core.Components.PFindComponentByInstanceGuid(&InstanceGuid)))) { hr = pComponent->Refs.HrAddReferenceByComponent ( pRefdByComponent); } else if (NULL != (pRefdByComponent = pNetConfig-> Core.Components.PFindComponentByInfId ( szValueName, NULL))) { hr = pComponent->Refs.HrAddReferenceByComponent ( pRefdByComponent); } else { hr = pComponent->Refs.HrAddReferenceBySoftware ( szValueName); } } } if (HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr) { hr = S_OK; }
RegCloseKey (hkeyRefCounts); }
RegCloseKey (hkeyInstance); } }
// If the instance key or the refcounts key don't exist, there is not
// much we can do about it. Don't fail for these reasons.
//
if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) { hr = S_OK; }
TraceHr (ttidError, FAL, hr, FALSE, "HrLoadComponentReferencesFromLegacy"); return hr; }
VOID UpgradeConnection ( IN const GUID& InstanceGuid, IN PCWSTR pszPnpId) { HRESULT hr; WCHAR szPath[_MAX_PATH]; HKEY hkeyConn;
Assert (pszPnpId && *pszPnpId);
// Connections uses a pnp id value as their back pointer to the pnp
// tree.
//
CreateInstanceKeyPath (NC_NET, InstanceGuid, szPath); wcscat (szPath, L"\\Connection"); hr = HrRegOpenKeyEx (HKEY_LOCAL_MACHINE, szPath, KEY_READ_WRITE, &hkeyConn);
if (S_OK == hr) { HrRegSetSz (hkeyConn, L"PnpInstanceId", pszPnpId); }
RegCloseKey(hkeyConn); }
HRESULT HrLoadNetworkConfigurationFromLegacy ( OUT CNetConfig* pNetConfig) { HRESULT hr; NETCLASS Class; PCWSTR pszSubtree; HKEY hkeySubtree; DWORD dwIndex; HKEY hkeyInstance; GUID InstanceGuid; UINT PassNumber;
// Get the value for whether WAN adapters comes first or last in
// adapter order. We need to give this to the stack table so it will
// know which way to order things.
//
Assert (FALSE == pNetConfig->Core.StackTable.m_fWanAdaptersFirst);
hr = HrOpenNetworkKey ( KEY_READ, &hkeySubtree);
if (S_OK == hr) { DWORD dwValue;
hr = HrRegQueryDword (hkeySubtree, L"WanAdaptersFirst", &dwValue);
if (S_OK == hr) { pNetConfig->Core.StackTable.m_fWanAdaptersFirst = !!dwValue; }
RegCloseKey (hkeySubtree); }
// We need two passes to correctly upgrade everything. Since filter
// devices reference an adapter, we need to have already read the
// information for all adapters before we can read information about
// a filter device and create a memory representation for it which
// references the memory representation of the adapter which it filters.
//
// The following structure should make this more clear. For each
// element in this array, we enumerate components in the specified
// class. Note that NC_NET is reference twice -- once for pass one
// and once for pass two. The code below uses the pass number to
// know whether it should be ignoring filter devices (in pass one)
// or ignoring adapters (in pass two, because they were already handled
// in pass one.) If it isn't clear by now, don't touch this code. ;-)
//
static const struct { NETCLASS Class; UINT PassNumber; } aPassInfo [] = { { NC_NET, 1 }, { NC_INFRARED, 1 }, { NC_NETTRANS, 1 }, { NC_NETCLIENT, 1 }, { NC_NETSERVICE, 1 }, { NC_NET, 2 }, };
for (UINT i = 0; i < celems(aPassInfo); i++) { Class = aPassInfo[i].Class; PassNumber = aPassInfo[i].PassNumber;
Assert (FIsValidNetClass(Class));
pszSubtree = MAP_NETCLASS_TO_NETWORK_SUBTREE[Class];
if (!FIsEnumerated (Class)) { hr = HrRegOpenKeyEx (HKEY_LOCAL_MACHINE, pszSubtree, KEY_READ, &hkeySubtree);
if (S_OK == hr) { DWORD cchGuid; WCHAR szInstanceGuid [c_cchGuidWithTerm]; FILETIME ftLastWrite;
for (dwIndex = 0; S_OK == hr; dwIndex++) { cchGuid = celems(szInstanceGuid);
hr = HrRegEnumKeyEx ( hkeySubtree, dwIndex, szInstanceGuid, &cchGuid, NULL, NULL, &ftLastWrite);
if ((S_OK == hr) && ((c_cchGuidWithTerm-1) == cchGuid)) { hr = IIDFromString (szInstanceGuid, &InstanceGuid); if (S_OK == hr) { hr = HrRegOpenKeyEx ( hkeySubtree, szInstanceGuid, KEY_READ, &hkeyInstance);
if (S_OK == hr) { hr = HrLoadAndAddComponentFromInstanceKey ( hkeyInstance, &InstanceGuid, Class, NULL, pNetConfig);
RegCloseKey (hkeyInstance); } } else { // Delete the key?
}
// Ignore any errors during the loop
hr = S_OK; } } if (HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr) { hr = S_OK; }
RegCloseKey (hkeySubtree); } } else { HDEVINFO hdi;
hr = HrSetupDiGetClassDevs (MAP_NETCLASS_TO_GUID[Class], NULL, NULL, DIGCF_PROFILE, &hdi);
if (S_OK == hr) { SP_DEVINFO_DATA deid; WCHAR szPnpId [2 * _MAX_PATH]; WCHAR szFilterName [_MAX_PATH]; BOOL fr;
for (dwIndex = 0; S_OK == hr; dwIndex++) { hr = HrSetupDiEnumDeviceInfo (hdi, dwIndex, &deid);
if (S_OK == hr) { fr = SetupDiGetDeviceInstanceId ( hdi, &deid, szPnpId, celems(szPnpId), NULL);
if (fr) { // We open with KEY_WRITE because we will be
// adding a new value to filter devices we
// upgrade.
//
hr = HrSetupDiOpenDevRegKey ( hdi, &deid, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_WRITE | KEY_READ, &hkeyInstance);
if (S_OK == hr) { LONG lr; ULONG cbGuid = sizeof(GUID);
lr = RegQueryGuid ( hkeyInstance, L"NetCfgInstanceId", &InstanceGuid, &cbGuid);
if (!lr) { BOOL fIsFilterDevice; HKEY hkeyNdi;
fIsFilterDevice = FALSE;
hr = HrRegOpenKeyEx ( hkeyInstance, L"Ndi", KEY_READ, &hkeyNdi);
if (S_OK == hr) { DWORD cbFilterName = sizeof(szFilterName);
hr = HrRegQuerySzBuffer ( hkeyNdi, L"FilterName", szFilterName, &cbFilterName);
if (S_OK == hr) { fIsFilterDevice = TRUE; }
RegCloseKey (hkeyNdi); }
// If it's a filter device, ignore it in
// pass one and handle it in pass two.
//
if (fIsFilterDevice && (2 == PassNumber)) { FUpgradeFilterDeviceInstanceKey ( pNetConfig, hkeyInstance, szFilterName); }
// If it's not a filter device, handle it
// in pass one and ignore it in pass two.
//
else if (!fIsFilterDevice && (1 == PassNumber)) { UpgradeConnection (InstanceGuid, szPnpId);
hr = HrLoadAndAddComponentFromInstanceKey ( hkeyInstance, &InstanceGuid, Class, szPnpId, pNetConfig); } }
RegCloseKey (hkeyInstance); } }
// Ignore any errors during the loop
hr = S_OK; } } if (HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr) { hr = S_OK; }
SetupDiDestroyDeviceInfoList (hdi); } } }
if (S_OK == hr) { hr = HrLoadComponentReferencesFromLegacy (pNetConfig); }
if (S_OK == hr) { CComponentList::iterator iter; CComponent* pComponent; CBindPath BindPath; CBindingSet BindSet; HKEY hkeyParent; HKEY hkeyDisabled;
// Upgrade disabled bindings.
//
for (iter = pNetConfig->Core.Components.begin(); iter != pNetConfig->Core.Components.end(); iter++) { pComponent = *iter; Assert (pComponent);
// Open the parent of the linkage key depending on what type
// of component this is.
//
if (FIsEnumerated (pComponent->Class()) || !pComponent->FHasService()) { hr = pComponent->HrOpenInstanceKey (KEY_READ, &hkeyParent, NULL, NULL); } else { hr = pComponent->HrOpenServiceKey (KEY_READ, &hkeyParent); }
// Open the Linkage\Disabled key.
//
if (S_OK == hr) { hr = HrRegOpenKeyEx (hkeyParent, L"Linkage\\Disabled", KEY_READ, &hkeyDisabled);
if (S_OK == hr) { PWSTR pmszBindPath;
hr = HrRegQueryMultiSzWithAlloc ( hkeyDisabled, L"BindPath", &pmszBindPath);
if (S_OK == hr) { PWSTR pszBindPath; PCWSTR pszBindName; PWSTR pszNext; CComponent* pOther;
// Get the components current bindings as they
// exist in the new engine. We won't disable
// any bindings that don't exist in this set.
//
(VOID) pNetConfig->Core.HrGetComponentBindings ( pComponent, GBF_DEFAULT, &BindSet);
// Iterate the multi-sz of disabled bindpaths.
//
for (pszBindPath = pmszBindPath; *pszBindPath; pszBindPath += wcslen(pszBindPath) + 1) { // The bindpath will start with this component
// that has the disabled bindings.
//
BindPath.Clear(); BindPath.HrAppendComponent (pComponent);
for (pszBindName = GetNextStringToken (pszBindPath, L"_", &pszNext); pszBindName && *pszBindName; pszBindName = GetNextStringToken (NULL, L"_", &pszNext)) { pOther = pNetConfig->Core.Components. PFindComponentByBindName ( NC_INVALID, pszBindName);
if (!pOther) { break; }
BindPath.HrAppendComponent (pOther); }
// If the bindpath is valid, disable it.
//
if (BindSet.FContainsBindPath (&BindPath)) { pNetConfig->Core.HrDisableBindPath (&BindPath); } }
MemFree (pmszBindPath); }
RegCloseKey (hkeyDisabled); }
RegCloseKey (hkeyParent); } }
// If we can't upgrade disabled bindings, no biggee.
//
hr = S_OK; }
TraceHr (ttidError, FAL, hr, FALSE, "HrLoadNetworkConfigurationFromLegacy"); return hr; }
|