677 lines
22 KiB
C++
677 lines
22 KiB
C++
#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;
|
|
}
|